1 Data

acc1_cancer_cells = readRDS("./Data/acc1_cancer_cells_15KnCount_V3.RDS")
all_acc_cancer_cells = readRDS("./Data/acc_cancer_cells_V4.RDS")
acc_all_cells = readRDS("./Data/acc_tpm_nCount_mito_no146_15k_with_ACC1_.RDS")
acc_cancerCells_noACC1 = readRDS("./Data/acc_cancer_no146_primaryonly15k_cancercells.rds")

luminal_pathways = c("CHARAFE_BREAST_CANCER_LUMINAL_VS_BASAL_DN","CHARAFE_BREAST_CANCER_LUMINAL_VS_BASAL_UP","CHARAFE_BREAST_CANCER_LUMINAL_VS_MESENCHYMAL_DN","CHARAFE_BREAST_CANCER_LUMINAL_VS_MESENCHYMAL_UP","HUPER_BREAST_BASAL_VS_LUMINAL_DN","LIM_MAMMARY_LUMINAL_PROGENITOR_UP","SMID_BREAST_CANCER_LUMINAL_B_UP" )

# add luminal pathwaysx 
luminal_gs = msigdbr(species = "Homo sapiens") %>%as.data.frame() %>% dplyr::filter(gs_name %in% luminal_pathways)%>% dplyr::distinct(gs_name, gene_symbol) %>% as.data.frame()

2 Parameters

3 functions

source_from_github(repositoy = "DEG_functions",version = "0.2.24")
source_from_github(repositoy = "HMSC_functions",version = "0.1.13",script_name = "functions.R")
source_from_github(repositoy = "cNMF_functions",version = "0.3.72",script_name = "cnmf_function_Harmony.R")

4 UMAP

DimPlot(object = acc1_cancer_cells,pt.size = 2)

deg = FindAllMarkers(object = acc1_cancer_cells,features = VariableFeatures(acc1_cancer_cells),densify = T)
Calculating cluster 0

  |                                                  | 0 % ~calculating  
  |+                                                 | 1 % ~04s          
  |+                                                 | 2 % ~04s          
  |++                                                | 3 % ~03s          
  |++                                                | 4 % ~03s          
  |+++                                               | 5 % ~03s          
  |+++                                               | 6 % ~03s          
  |++++                                              | 7 % ~03s          
  |++++                                              | 8 % ~03s          
  |+++++                                             | 9 % ~03s          
  |+++++                                             | 10% ~03s          
  |++++++                                            | 11% ~03s          
  |++++++                                            | 12% ~03s          
  |+++++++                                           | 13% ~03s          
  |+++++++                                           | 14% ~03s          
  |++++++++                                          | 15% ~03s          
  |++++++++                                          | 16% ~03s          
  |+++++++++                                         | 17% ~03s          
  |+++++++++                                         | 18% ~03s          
  |++++++++++                                        | 19% ~03s          
  |++++++++++                                        | 20% ~03s          
  |+++++++++++                                       | 21% ~03s          
  |+++++++++++                                       | 22% ~03s          
  |++++++++++++                                      | 23% ~03s          
  |++++++++++++                                      | 24% ~03s          
  |+++++++++++++                                     | 25% ~02s          
  |+++++++++++++                                     | 26% ~02s          
  |++++++++++++++                                    | 27% ~02s          
  |++++++++++++++                                    | 28% ~02s          
  |+++++++++++++++                                   | 29% ~02s          
  |+++++++++++++++                                   | 30% ~02s          
  |++++++++++++++++                                  | 31% ~02s          
  |++++++++++++++++                                  | 32% ~03s          
  |+++++++++++++++++                                 | 33% ~03s          
  |+++++++++++++++++                                 | 34% ~02s          
  |++++++++++++++++++                                | 35% ~02s          
  |++++++++++++++++++                                | 36% ~02s          
  |+++++++++++++++++++                               | 37% ~02s          
  |+++++++++++++++++++                               | 38% ~02s          
  |++++++++++++++++++++                              | 39% ~02s          
  |++++++++++++++++++++                              | 40% ~02s          
  |+++++++++++++++++++++                             | 41% ~02s          
  |+++++++++++++++++++++                             | 42% ~02s          
  |++++++++++++++++++++++                            | 43% ~02s          
  |++++++++++++++++++++++                            | 44% ~02s          
  |+++++++++++++++++++++++                           | 45% ~02s          
  |+++++++++++++++++++++++                           | 46% ~02s          
  |++++++++++++++++++++++++                          | 47% ~02s          
  |++++++++++++++++++++++++                          | 48% ~02s          
  |+++++++++++++++++++++++++                         | 49% ~02s          
  |+++++++++++++++++++++++++                         | 50% ~02s          
  |++++++++++++++++++++++++++                        | 51% ~02s          
  |++++++++++++++++++++++++++                        | 52% ~02s          
  |+++++++++++++++++++++++++++                       | 53% ~02s          
  |+++++++++++++++++++++++++++                       | 54% ~02s          
  |++++++++++++++++++++++++++++                      | 55% ~02s          
  |++++++++++++++++++++++++++++                      | 56% ~02s          
  |+++++++++++++++++++++++++++++                     | 57% ~02s          
  |+++++++++++++++++++++++++++++                     | 58% ~02s          
  |++++++++++++++++++++++++++++++                    | 59% ~02s          
  |++++++++++++++++++++++++++++++                    | 60% ~01s          
  |+++++++++++++++++++++++++++++++                   | 61% ~01s          
  |+++++++++++++++++++++++++++++++                   | 62% ~01s          
  |++++++++++++++++++++++++++++++++                  | 63% ~01s          
  |++++++++++++++++++++++++++++++++                  | 64% ~01s          
  |+++++++++++++++++++++++++++++++++                 | 65% ~01s          
  |+++++++++++++++++++++++++++++++++                 | 66% ~01s          
  |++++++++++++++++++++++++++++++++++                | 67% ~01s          
  |++++++++++++++++++++++++++++++++++                | 68% ~01s          
  |+++++++++++++++++++++++++++++++++++               | 69% ~01s          
  |+++++++++++++++++++++++++++++++++++               | 70% ~01s          
  |++++++++++++++++++++++++++++++++++++              | 71% ~01s          
  |++++++++++++++++++++++++++++++++++++              | 72% ~01s          
  |+++++++++++++++++++++++++++++++++++++             | 73% ~01s          
  |+++++++++++++++++++++++++++++++++++++             | 74% ~01s          
  |++++++++++++++++++++++++++++++++++++++            | 75% ~01s          
  |++++++++++++++++++++++++++++++++++++++            | 76% ~01s          
  |+++++++++++++++++++++++++++++++++++++++           | 77% ~01s          
  |+++++++++++++++++++++++++++++++++++++++           | 78% ~01s          
  |++++++++++++++++++++++++++++++++++++++++          | 79% ~01s          
  |++++++++++++++++++++++++++++++++++++++++          | 80% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++         | 81% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++         | 82% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++        | 83% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++        | 84% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++++       | 85% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++++       | 86% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++      | 87% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++      | 88% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++     | 89% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++     | 90% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++    | 91% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++    | 92% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++   | 93% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++   | 94% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++  | 95% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++  | 96% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++++ | 97% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 99% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=04s  
Calculating cluster 1

  |                                                  | 0 % ~calculating  
  |+                                                 | 1 % ~04s          
  |+                                                 | 2 % ~04s          
  |++                                                | 3 % ~05s          
  |++                                                | 4 % ~04s          
  |+++                                               | 5 % ~04s          
  |+++                                               | 6 % ~04s          
  |++++                                              | 7 % ~04s          
  |++++                                              | 8 % ~04s          
  |+++++                                             | 9 % ~03s          
  |+++++                                             | 10% ~03s          
  |++++++                                            | 11% ~03s          
  |++++++                                            | 12% ~03s          
  |+++++++                                           | 13% ~03s          
  |+++++++                                           | 14% ~03s          
  |++++++++                                          | 15% ~03s          
  |++++++++                                          | 16% ~03s          
  |+++++++++                                         | 17% ~03s          
  |+++++++++                                         | 18% ~03s          
  |++++++++++                                        | 19% ~03s          
  |++++++++++                                        | 20% ~03s          
  |+++++++++++                                       | 21% ~03s          
  |+++++++++++                                       | 22% ~03s          
  |++++++++++++                                      | 23% ~03s          
  |++++++++++++                                      | 24% ~03s          
  |+++++++++++++                                     | 25% ~03s          
  |+++++++++++++                                     | 26% ~03s          
  |++++++++++++++                                    | 27% ~02s          
  |++++++++++++++                                    | 28% ~02s          
  |+++++++++++++++                                   | 29% ~02s          
  |+++++++++++++++                                   | 30% ~02s          
  |++++++++++++++++                                  | 31% ~02s          
  |++++++++++++++++                                  | 32% ~02s          
  |+++++++++++++++++                                 | 33% ~02s          
  |+++++++++++++++++                                 | 34% ~02s          
  |++++++++++++++++++                                | 35% ~02s          
  |++++++++++++++++++                                | 36% ~02s          
  |+++++++++++++++++++                               | 37% ~02s          
  |+++++++++++++++++++                               | 38% ~02s          
  |++++++++++++++++++++                              | 39% ~02s          
  |++++++++++++++++++++                              | 40% ~02s          
  |+++++++++++++++++++++                             | 41% ~02s          
  |+++++++++++++++++++++                             | 42% ~02s          
  |++++++++++++++++++++++                            | 43% ~02s          
  |++++++++++++++++++++++                            | 44% ~02s          
  |+++++++++++++++++++++++                           | 45% ~02s          
  |+++++++++++++++++++++++                           | 46% ~02s          
  |++++++++++++++++++++++++                          | 47% ~02s          
  |++++++++++++++++++++++++                          | 48% ~02s          
  |+++++++++++++++++++++++++                         | 49% ~02s          
  |+++++++++++++++++++++++++                         | 50% ~02s          
  |++++++++++++++++++++++++++                        | 51% ~02s          
  |++++++++++++++++++++++++++                        | 52% ~02s          
  |+++++++++++++++++++++++++++                       | 53% ~02s          
  |+++++++++++++++++++++++++++                       | 54% ~02s          
  |++++++++++++++++++++++++++++                      | 55% ~02s          
  |++++++++++++++++++++++++++++                      | 56% ~01s          
  |+++++++++++++++++++++++++++++                     | 57% ~01s          
  |+++++++++++++++++++++++++++++                     | 58% ~02s          
  |++++++++++++++++++++++++++++++                    | 59% ~02s          
  |++++++++++++++++++++++++++++++                    | 60% ~01s          
  |+++++++++++++++++++++++++++++++                   | 61% ~01s          
  |+++++++++++++++++++++++++++++++                   | 62% ~01s          
  |++++++++++++++++++++++++++++++++                  | 63% ~01s          
  |++++++++++++++++++++++++++++++++                  | 64% ~01s          
  |+++++++++++++++++++++++++++++++++                 | 65% ~01s          
  |+++++++++++++++++++++++++++++++++                 | 66% ~01s          
  |++++++++++++++++++++++++++++++++++                | 67% ~01s          
  |++++++++++++++++++++++++++++++++++                | 68% ~01s          
  |+++++++++++++++++++++++++++++++++++               | 69% ~01s          
  |+++++++++++++++++++++++++++++++++++               | 70% ~01s          
  |++++++++++++++++++++++++++++++++++++              | 71% ~01s          
  |++++++++++++++++++++++++++++++++++++              | 72% ~01s          
  |+++++++++++++++++++++++++++++++++++++             | 73% ~01s          
  |+++++++++++++++++++++++++++++++++++++             | 74% ~01s          
  |++++++++++++++++++++++++++++++++++++++            | 75% ~01s          
  |++++++++++++++++++++++++++++++++++++++            | 76% ~01s          
  |+++++++++++++++++++++++++++++++++++++++           | 77% ~01s          
  |+++++++++++++++++++++++++++++++++++++++           | 78% ~01s          
  |++++++++++++++++++++++++++++++++++++++++          | 79% ~01s          
  |++++++++++++++++++++++++++++++++++++++++          | 80% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++         | 81% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++         | 82% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++        | 83% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++        | 84% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++++       | 85% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++++       | 86% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++++      | 87% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++      | 88% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++     | 89% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++     | 90% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++    | 91% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++    | 92% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++   | 93% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++   | 94% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++  | 95% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++  | 96% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++++ | 97% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 99% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=04s  
Calculating cluster 2

  |                                                  | 0 % ~calculating  
  |+                                                 | 1 % ~04s          
  |++                                                | 2 % ~04s          
  |++                                                | 3 % ~04s          
  |+++                                               | 4 % ~04s          
  |+++                                               | 5 % ~03s          
  |++++                                              | 6 % ~03s          
  |++++                                              | 7 % ~03s          
  |+++++                                             | 8 % ~03s          
  |+++++                                             | 9 % ~03s          
  |++++++                                            | 10% ~03s          
  |++++++                                            | 11% ~03s          
  |+++++++                                           | 12% ~03s          
  |+++++++                                           | 13% ~03s          
  |++++++++                                          | 14% ~03s          
  |++++++++                                          | 15% ~03s          
  |+++++++++                                         | 16% ~03s          
  |+++++++++                                         | 17% ~03s          
  |++++++++++                                        | 18% ~03s          
  |++++++++++                                        | 19% ~03s          
  |+++++++++++                                       | 20% ~03s          
  |+++++++++++                                       | 21% ~03s          
  |++++++++++++                                      | 22% ~03s          
  |++++++++++++                                      | 23% ~03s          
  |+++++++++++++                                     | 24% ~03s          
  |+++++++++++++                                     | 25% ~03s          
  |++++++++++++++                                    | 26% ~03s          
  |++++++++++++++                                    | 27% ~03s          
  |+++++++++++++++                                   | 28% ~03s          
  |+++++++++++++++                                   | 29% ~03s          
  |++++++++++++++++                                  | 30% ~03s          
  |++++++++++++++++                                  | 31% ~02s          
  |+++++++++++++++++                                 | 32% ~02s          
  |+++++++++++++++++                                 | 33% ~02s          
  |++++++++++++++++++                                | 34% ~02s          
  |++++++++++++++++++                                | 35% ~02s          
  |+++++++++++++++++++                               | 36% ~02s          
  |+++++++++++++++++++                               | 37% ~02s          
  |++++++++++++++++++++                              | 38% ~02s          
  |++++++++++++++++++++                              | 39% ~02s          
  |+++++++++++++++++++++                             | 40% ~02s          
  |+++++++++++++++++++++                             | 41% ~02s          
  |++++++++++++++++++++++                            | 42% ~02s          
  |++++++++++++++++++++++                            | 43% ~02s          
  |+++++++++++++++++++++++                           | 44% ~02s          
  |+++++++++++++++++++++++                           | 45% ~02s          
  |++++++++++++++++++++++++                          | 46% ~02s          
  |++++++++++++++++++++++++                          | 47% ~02s          
  |+++++++++++++++++++++++++                         | 48% ~02s          
  |+++++++++++++++++++++++++                         | 49% ~02s          
  |++++++++++++++++++++++++++                        | 51% ~02s          
  |++++++++++++++++++++++++++                        | 52% ~02s          
  |+++++++++++++++++++++++++++                       | 53% ~02s          
  |+++++++++++++++++++++++++++                       | 54% ~02s          
  |++++++++++++++++++++++++++++                      | 55% ~02s          
  |++++++++++++++++++++++++++++                      | 56% ~02s          
  |+++++++++++++++++++++++++++++                     | 57% ~01s          
  |+++++++++++++++++++++++++++++                     | 58% ~01s          
  |++++++++++++++++++++++++++++++                    | 59% ~01s          
  |++++++++++++++++++++++++++++++                    | 60% ~01s          
  |+++++++++++++++++++++++++++++++                   | 61% ~01s          
  |+++++++++++++++++++++++++++++++                   | 62% ~01s          
  |++++++++++++++++++++++++++++++++                  | 63% ~01s          
  |++++++++++++++++++++++++++++++++                  | 64% ~01s          
  |+++++++++++++++++++++++++++++++++                 | 65% ~01s          
  |+++++++++++++++++++++++++++++++++                 | 66% ~01s          
  |++++++++++++++++++++++++++++++++++                | 67% ~01s          
  |++++++++++++++++++++++++++++++++++                | 68% ~01s          
  |+++++++++++++++++++++++++++++++++++               | 69% ~01s          
  |+++++++++++++++++++++++++++++++++++               | 70% ~01s          
  |++++++++++++++++++++++++++++++++++++              | 71% ~01s          
  |++++++++++++++++++++++++++++++++++++              | 72% ~01s          
  |+++++++++++++++++++++++++++++++++++++             | 73% ~01s          
  |+++++++++++++++++++++++++++++++++++++             | 74% ~01s          
  |++++++++++++++++++++++++++++++++++++++            | 75% ~01s          
  |++++++++++++++++++++++++++++++++++++++            | 76% ~01s          
  |+++++++++++++++++++++++++++++++++++++++           | 77% ~01s          
  |+++++++++++++++++++++++++++++++++++++++           | 78% ~01s          
  |++++++++++++++++++++++++++++++++++++++++          | 79% ~01s          
  |++++++++++++++++++++++++++++++++++++++++          | 80% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++         | 81% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++         | 82% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++        | 83% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++        | 84% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++++       | 85% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++++       | 86% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++++      | 87% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++      | 88% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++     | 89% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++     | 90% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++    | 91% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++    | 92% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++   | 93% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++   | 94% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++  | 95% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++  | 96% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++++ | 97% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 99% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=04s  
Calculating cluster 3

  |                                                  | 0 % ~calculating  
  |+                                                 | 1 % ~04s          
  |+                                                 | 2 % ~04s          
  |++                                                | 3 % ~03s          
  |++                                                | 4 % ~03s          
  |+++                                               | 5 % ~03s          
  |+++                                               | 6 % ~03s          
  |++++                                              | 7 % ~03s          
  |++++                                              | 8 % ~03s          
  |+++++                                             | 9 % ~03s          
  |+++++                                             | 10% ~03s          
  |++++++                                            | 11% ~03s          
  |++++++                                            | 12% ~03s          
  |+++++++                                           | 13% ~03s          
  |+++++++                                           | 14% ~03s          
  |++++++++                                          | 15% ~03s          
  |++++++++                                          | 16% ~03s          
  |+++++++++                                         | 17% ~03s          
  |+++++++++                                         | 18% ~03s          
  |++++++++++                                        | 19% ~03s          
  |++++++++++                                        | 20% ~03s          
  |+++++++++++                                       | 21% ~03s          
  |+++++++++++                                       | 22% ~03s          
  |++++++++++++                                      | 23% ~03s          
  |++++++++++++                                      | 24% ~03s          
  |+++++++++++++                                     | 25% ~03s          
  |+++++++++++++                                     | 26% ~03s          
  |++++++++++++++                                    | 27% ~03s          
  |++++++++++++++                                    | 28% ~02s          
  |+++++++++++++++                                   | 29% ~02s          
  |+++++++++++++++                                   | 30% ~02s          
  |++++++++++++++++                                  | 31% ~02s          
  |++++++++++++++++                                  | 32% ~02s          
  |+++++++++++++++++                                 | 33% ~02s          
  |+++++++++++++++++                                 | 34% ~02s          
  |++++++++++++++++++                                | 35% ~02s          
  |++++++++++++++++++                                | 36% ~02s          
  |+++++++++++++++++++                               | 37% ~02s          
  |+++++++++++++++++++                               | 38% ~02s          
  |++++++++++++++++++++                              | 39% ~02s          
  |++++++++++++++++++++                              | 40% ~02s          
  |+++++++++++++++++++++                             | 41% ~02s          
  |+++++++++++++++++++++                             | 42% ~02s          
  |++++++++++++++++++++++                            | 43% ~02s          
  |++++++++++++++++++++++                            | 44% ~02s          
  |+++++++++++++++++++++++                           | 45% ~02s          
  |+++++++++++++++++++++++                           | 46% ~02s          
  |++++++++++++++++++++++++                          | 47% ~02s          
  |++++++++++++++++++++++++                          | 48% ~02s          
  |+++++++++++++++++++++++++                         | 49% ~02s          
  |+++++++++++++++++++++++++                         | 50% ~02s          
  |++++++++++++++++++++++++++                        | 51% ~02s          
  |++++++++++++++++++++++++++                        | 52% ~02s          
  |+++++++++++++++++++++++++++                       | 53% ~02s          
  |+++++++++++++++++++++++++++                       | 54% ~02s          
  |++++++++++++++++++++++++++++                      | 55% ~02s          
  |++++++++++++++++++++++++++++                      | 56% ~02s          
  |+++++++++++++++++++++++++++++                     | 57% ~02s          
  |+++++++++++++++++++++++++++++                     | 58% ~01s          
  |++++++++++++++++++++++++++++++                    | 59% ~01s          
  |++++++++++++++++++++++++++++++                    | 60% ~01s          
  |+++++++++++++++++++++++++++++++                   | 61% ~01s          
  |+++++++++++++++++++++++++++++++                   | 62% ~01s          
  |++++++++++++++++++++++++++++++++                  | 63% ~01s          
  |++++++++++++++++++++++++++++++++                  | 64% ~01s          
  |+++++++++++++++++++++++++++++++++                 | 65% ~01s          
  |+++++++++++++++++++++++++++++++++                 | 66% ~01s          
  |++++++++++++++++++++++++++++++++++                | 67% ~01s          
  |++++++++++++++++++++++++++++++++++                | 68% ~01s          
  |+++++++++++++++++++++++++++++++++++               | 69% ~01s          
  |+++++++++++++++++++++++++++++++++++               | 70% ~01s          
  |++++++++++++++++++++++++++++++++++++              | 71% ~01s          
  |++++++++++++++++++++++++++++++++++++              | 72% ~01s          
  |+++++++++++++++++++++++++++++++++++++             | 73% ~01s          
  |+++++++++++++++++++++++++++++++++++++             | 74% ~01s          
  |++++++++++++++++++++++++++++++++++++++            | 75% ~01s          
  |++++++++++++++++++++++++++++++++++++++            | 76% ~01s          
  |+++++++++++++++++++++++++++++++++++++++           | 77% ~01s          
  |+++++++++++++++++++++++++++++++++++++++           | 78% ~01s          
  |++++++++++++++++++++++++++++++++++++++++          | 79% ~01s          
  |++++++++++++++++++++++++++++++++++++++++          | 80% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++         | 81% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++         | 82% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++        | 83% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++        | 84% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++++       | 85% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++++       | 86% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++      | 87% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++      | 88% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++     | 89% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++     | 90% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++    | 91% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++    | 92% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++   | 93% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++   | 94% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++  | 95% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++  | 96% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++++ | 97% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 99% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=03s  
for (cluster in unique(deg$cluster)) {
  print(deg[deg$cluster == cluster,])
}
for (cluster in unique(deg$cluster)) {
  deg_of_cluster = deg[deg$cluster == cluster,]
  enrichment_analysis(deg_of_cluster,background =VariableFeatures(acc1_cancer_cells),fdr_Cutoff = 0.01,ident.1 = paste("Cluster",cluster),ident.2 =  paste("Cluster",cluster),show_by = 1)
}

NA
NA

4.1 features UMAP

FeaturePlot(object = acc1_cancer_cells,features = c("TP63","ACTA2","IL12B","CNN1"))
Warning in FeaturePlot(object = acc1_cancer_cells, features = c("TP63",  :
  All cells have the same value (0) of IL12B.

5 Enrichment analysis HMSC vs ACC

all_acc_cancer_cells = SetIdent(all_acc_cancer_cells, value ="patient.ident")
acc_deg <- FindMarkers(all_acc_cancer_cells, ident.1 = "HMSC",logfc.threshold = 1.5,features = VariableFeatures(all_acc_cancer_cells))
enrichment_analysis(acc_deg,background = VariableFeatures(all_acc_cancer_cells),fdr_Cutoff = 0.01,ident.1 = "HMSC",ident.2 = "ACC",show_by = 1)

5.1 cell cycle filtering

hallmark_name = "GO_MITOTIC_CELL_CYCLE"
genesets  =getGmt("./Data/h.all.v7.0.symbols.pluscc.gmt")
var_features=acc_cancerCells_noACC1@assays$RNA@var.features
geneIds= genesets[[hallmark_name]]@geneIds
score <- apply(acc_cancerCells_noACC1@assays$RNA@scale.data[intersect(geneIds,var_features),],2,mean)
acc_cancerCells_noACC1=AddMetaData(acc_cancerCells_noACC1,score,hallmark_name)

hallmark_name = "GO_MITOTIC_CELL_CYCLE"
genesets  =getGmt("./Data/h.all.v7.0.symbols.pluscc.gmt")
var_features=acc1_cancer_cells@assays$RNA@var.features
geneIds= genesets[[hallmark_name]]@geneIds
score <- apply(acc1_cancer_cells@assays$RNA@scale.data[intersect(geneIds,var_features),],2,mean)
acc1_cancer_cells=AddMetaData(acc1_cancer_cells,score,hallmark_name)


# hallmark_name = "GO_MITOTIC_CELL_CYCLE"
# genesets  =getGmt("./Data/h.all.v7.0.symbols.pluscc.gmt")
# var_features=acc1_cancer_cells@assays$RNA@var.features
# geneIds= genesets[[hallmark_name]]@geneIds
# score <- apply(acc1_cancer_cells@assays$RNA@scale.data[intersect(geneIds,var_features),],2,mean)
# acc1_cancer_cells=AddMetaData(acc1_cancer_cells,score,hallmark_name)
library(highcharter) 
options(highcharter.theme = hc_theme_smpl(tooltip = list(valueDecimals = 2)))

cc_scores = FetchData(object = acc1_cancer_cells,vars = "GO_MITOTIC_CELL_CYCLE")
 hchart(
  density(cc_scores$GO_MITOTIC_CELL_CYCLE), 
  type = "area", name = "GO_MITOTIC_CELL_CYCLE"
  )
NA
cc_scores = FetchData(object = acc_cancerCells_noACC1,vars = "GO_MITOTIC_CELL_CYCLE")
 hchart(
  density(cc_scores$GO_MITOTIC_CELL_CYCLE), 
  type = "area", name = "GO_MITOTIC_CELL_CYCLE"
  )
NA
acc_cc_scores = FetchData(object = acc_cancerCells_noACC1,vars = "GO_MITOTIC_CELL_CYCLE")
hmsc_cc_scores = FetchData(object = acc1_cancer_cells,vars = "GO_MITOTIC_CELL_CYCLE")

ggplot() +
  geom_density(aes(GO_MITOTIC_CELL_CYCLE, fill = "ACC"), alpha = .2, data = acc_cc_scores) +
  geom_density(aes(GO_MITOTIC_CELL_CYCLE, fill = "HMSC"), alpha = .2, data = hmsc_cc_scores) +
  scale_fill_manual(name = "Dataset", values = c(ACC = "red", HMSC = "green"))+ geom_vline(aes(xintercept=0.15),
            color="blue", linetype="dashed", size=1)

5.1.1 Before cc filtering


#filter:
all_acc_cancer_cells_ccFiltered=all_acc_cancer_cells[,all_acc_cancer_cells@meta.data[[hallmark_name]]< 0.15]


min_threshold = min(all_acc_cancer_cells$GO_MITOTIC_CELL_CYCLE)
max_threshold = max(all_acc_cancer_cells$GO_MITOTIC_CELL_CYCLE)
library(viridis)
Loading required package: viridisLite
FeaturePlot(object = all_acc_cancer_cells,features = hallmark_name) + ggtitle("Before cc filtering")  & scale_color_gradientn(colours = plasma(n = 10, direction = -1), limits = c(min_threshold, max_threshold))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Warning in grSoftVersion() :
  unable to load shared object '/usr/local/lib/R/modules//R_X11.so':
  libXt.so.6: cannot open shared object file: No such file or directory

5.1.2 After cc filtering

FeaturePlot(object = all_acc_cancer_cells_ccFiltered,features = hallmark_name) + ggtitle("After cc filtering") & scale_color_gradientn(colours = plasma(n = 10, direction = -1), limits = c(min_threshold, max_threshold))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.

5.2 Enrichment analysis filtered HMSC vs ACC

1
patient.ident = all_acc_cancer_cells_ccFiltered$patient.ident %>% as.data.frame()
patient.ident[,1] = as.character(patient.ident[,1])
patient.ident[patient.ident[,1] == "ACC1",] = "HMSC"
patient.ident[,1] = as.factor(patient.ident[,1])
all_acc_cancer_cells_ccFiltered = AddMetaData(object = all_acc_cancer_cells_ccFiltered,metadata = patient.ident,col.name = "patient.ident")
all_acc_cancer_cells_ccFiltered = SetIdent(all_acc_cancer_cells_ccFiltered, value ="patient.ident")
acc_deg <- FindMarkers(all_acc_cancer_cells_ccFiltered, ident.1 = "HMSC",logfc.threshold = 1.5,features = VariableFeatures(all_acc_cancer_cells_ccFiltered))
enrichment_analysis(acc_deg,background = VariableFeatures(all_acc_cancer_cells_ccFiltered),fdr_Cutoff = 0.01,ident.1 = "HMSC",ident.2 = "ACC",show_by = 1)

6 MYB expression

all_acc_cancer_cells = SetIdent(object = all_acc_cancer_cells,value = "patient.ident") #active snn graph
FeaturePlot(object = all_acc_cancer_cells,features = "MYB",label = T)

all_acc_cancer_cells = SetIdent(object = all_acc_cancer_cells,value = "patient.ident") #active snn graph
FeaturePlot(object = all_acc_cancer_cells,features = "MYB",label = T)

7 CNV

new.cluster.ids <- c("cancer", #0
                     "cancer", #1
                     "CAF", #2
                     "cancer", #3
                     "Endothelial", #4
                     "cancer", #5
                     "cancer", #6
                     "CAF", #7
                     "CAF", #8
                     "CAF", #9
                     "cancer", #10
                     "CAF", #11
                     "cancer", #12
                     "cancer", #13
                     "cancer", #14
                     "cancer", #15
                     "cancer", #16
                     "WBC", #17
                     "CAF" #18
                     )
#rename idents:
acc_all_cells = SetIdent(object = acc_all_cells,value = "RNA_snn_res.1") #active snn graph
names(new.cluster.ids) <- levels(acc_all_cells) #add snn graph levels to new.cluster.ids
acc_all_cells@meta.data[["seurat_clusters"]] = acc_all_cells@meta.data[["RNA_snn_res.1"]]
acc_all_cells = SetIdent(object = acc_all_cells,value = "seurat_clusters")
acc_all_cells <- RenameIdents(acc_all_cells, new.cluster.ids) 

# divide "cancer" into patients:
cell_types = acc_all_cells@active.ident %>% as.data.frame()
cell_types[,1]<- as.character(cell_types[,1])
cell_types = cbind(cell_types,acc_all_cells$patient.ident) %>% setnames(old = names(.), 
         new = c('cell_type','patient'))
cell_types[cell_types$cell_type == "cancer",] = cell_types[cell_types$cell_type == "cancer",2]


# hmsc_rows = (startsWith(x = rownames(cell_types),prefix = "ACC.plate2") | startsWith(x = rownames(cell_types),prefix = "ACC1.")) & cell_types[,1] == "cancer" 
# acc_rows = !(startsWith(x = rownames(cell_types),prefix = "ACC.plate2") | startsWith(x = rownames(cell_types),prefix = "ACC1.")) & cell_types[,1] == "cancer" 
# cell_types[,1][hmsc_rows]  = "HMSC"
# cell_types[,1][acc_rows]  = "ACC"

#add to metadata:
cell_types[,2] = NULL 
cell_types[cell_types$cell_type == "ACC1",] = "HMSC"
acc_all_cells = AddMetaData(object =acc_all_cells ,metadata = cell_types,col.name = "cell.type")

7.1 CNV UMAP

library(infercnv)
library(tidyverse)
acc_annotation  = as.data.frame(acc_all_cells@meta.data[,"cell.type",drop = F])
acc_annotation = acc_annotation %>% rownames_to_column("orig.ident") 
acc_annotation = acc_annotation %>% mutate(orig.ident = gsub(x = acc_annotation$orig.ident,pattern = "\\.", replacement = "-") %>% 
  gsub(pattern = "_", replacement = "-"))
  

write.table(acc_annotation, "./Data/inferCNV/acc_annotation.txt", append = FALSE, 
            sep = "\t", dec = ".",row.names = FALSE, col.names = F)

infercnv_obj = CreateInfercnvObject(raw_counts_matrix="./Data/inferCNV/all.4icnv.txt", 
                                    annotations_file="./Data/inferCNV/acc_annotation.txt",
                                    delim="\t",gene_order_file="./Data/inferCNV/gencode_v19_gene_pos.txt"
                                    ,ref_group_names=c("CAF", "Endothelial", "WBC")) #groups of normal cells

infercnv_obj_default = infercnv::run(infercnv_obj, cutoff=1, out_dir='./Data/inferCNV/infercnv_output',
                                     cluster_by_groups=T, plot_steps=FALSE,
                                     denoise=TRUE, HMM=FALSE, no_prelim_plot=TRUE,
                                     png_res=300)
plot_cnv(infercnv_obj_default, output_format = "png",  write_expr_matrix = FALSE,out_dir = "./Data/inferCNV/",png_res   =800,obs_title = "Malignant cells",ref_title = "Normal cells")


cluster.info=FetchData(acc_all_cells,c("ident","orig.ident","UMAP_1","UMAP_2","nCount_RNA","nFeature_RNA","percent.mt","patient.ident","seurat_clusters"))
cluster.info$cell=rownames(cluster.info)

library(limma)
smoothed=apply(infercnv_obj_default@expr.data,2,tricubeMovingAverage, span=0.01)
cnsig=sqrt(apply((smoothed-1)^2,2,mean))
umap=cluster.info
names(cnsig)=umap$cell

acc_all_cells <- AddMetaData(object = acc_all_cells, metadata = cnsig, col.name = "copynumber")
acc_all_cells = SetIdent(object = acc_all_cells,value = "cell.type")
FeaturePlot(acc_all_cells, "copynumber",pt.size = 1, cols = c("lightblue","orange","red","darkred"),label = T,repel = T)
acc_cancer_cells <- AddMetaData(object = acc_cancer_cells, metadata = cnsig, col.name = "copynumber")
acc_cancer_cells = SetIdent(object = acc_cancer_cells,value = "cell.type")
FeaturePlot(acc_cancer_cells, "copynumber",pt.size = 1, cols = c("lightblue","orange","red","darkred"),label = T,repel = T)

7.2 CNV plot

CNV plot

7.3 CNV subtypes

cnv_subtypes = as.data.frame(cutree(infercnv_obj_default@tumor_subclusters[["hc"]][["HMSC"]], k = 2))
names(cnv_subtypes)[1] = "cnv.cluster"
rownames(cnv_subtypes) = rownames(cnv_subtypes) %>% gsub(pattern = "-",replacement = "\\.")
cnv_subtypes [,1] = as.character(cnv_subtypes[,1])
infercnv.observations = data.frame(fread(file = "./Data/inferCNV/infercnv.observations.txt"), row.names=1)
names_to_keep = colnames(infercnv.observations) %in% (colnames(acc1_cancer_cells) %>% gsub(pattern = "_",replacement = "\\."))
infercnv.observations = infercnv.observations[,names_to_keep]

rownames(cnv_subtypes) = rownames(cnv_subtypes) %>% gsub(pattern = "2\\.",replacement = "2_")
rownames(cnv_subtypes) = rownames(cnv_subtypes) %>% gsub(pattern = "3\\.",replacement = "3_")
acc1_cancer_cells = AddMetaData(object = acc1_cancer_cells,metadata = cnv_subtypes)
DimPlot(acc1_cancer_cells,group.by = "cnv.cluster",pt.size = 2)

8 Myo-Lum score

8.1 Original score

original_myo_genes = c( "TP63", "TP73", "CAV1", "CDH3", "KRT5", "KRT14", "ACTA2", "TAGLN", "MYLK", "DKK3")
original_lum_genes = c("KIT", "EHF", "ELF5", "KRT7", "CLDN3", "CLDN4", "CD24", "LGALS3", "LCN2", "SLPI" )
calculate_score(dataset = all_acc_cancer_cells,myo_genes = original_myo_genes,lum_genes = original_lum_genes)
correlation of lum score and myo score: -0.45
correlation of lum score and original lum score: 1
correlation of myo score and original myo score: 1

8.2 Original score of ACC1

calculate_score(dataset = acc1_cancer_cells,myo_genes = original_myo_genes,lum_genes = original_lum_genes,lum_threshold = 0,myo_threshold = 0)
Warning: Could not find TP73 in the default search locations, found in RNA assay instead
Warning: Could not find MYLK in the default search locations, found in RNA assay instead
Warning: Could not find CLDN3 in the default search locations, found in RNA assay instead
Warning: Could not find CD24 in the default search locations, found in RNA assay instead
correlation of lum score and myo score: -0.11

8.3 0.35 Most correlated score

8.3.1 Myo genes

myo_protein_markers = c("CNN1", "TP63","ACTA2")
top_myo  = top_correlated(dataset = acc1_cancer_cells, genes = myo_protein_markers,threshold = 0.35)
print("Number of genes = " %>% paste(length(top_myo)))
[1] "Number of genes =  20"
message("Names of genes:")
Names of genes:
top_myo %>% head(30)
 [1] "COL16A1"     "RP1-39G22.4" "ACTG2"       "CD200"       "MYLK"        "TP63"        "KCNMB1"      "ADAMTS2"     "LOXL2"      
[10] "TPM2"        "CLIC3"       "SNCG"        "ACTA2"       "TAGLN"       "A2M"         "NGFR"        "CNN1"        "PPP1R14A"   
[19] "MYL9"        "POM121L9P"  
message("Genes that also apeared in the original score:")
Genes that also apeared in the original score:
base::intersect(top_myo,original_myo_genes) 
[1] "MYLK"  "TP63"  "ACTA2" "TAGLN"
myo_enrich_res = genes_vec_enrichment(genes = top_myo,background = rownames(acc1_cancer_cells),homer = T,title = "myo top enrichment",custom_pathways = luminal_gs)

myo_enrich_res

8.3.2 Lum genes

lum_protein_markers = c("KIT")
top_lum  = top_correlated(dataset = acc1_cancer_cells, genes = lum_protein_markers,threshold = 0.35,n_vargenes = 5000)
print("Number of genes = " %>% paste(length(top_lum)))
[1] "Number of genes =  5"
message("Names of genes:")
Names of genes:
top_lum %>% head(30)
[1] "B3GNT2"  "GLRB"    "EFNA5"   "ALDH3B2" "CCND1"  
message("Genes that also apeared in the original score:")
Genes that also apeared in the original score:
base::intersect(top_lum,original_lum_genes) 
character(0)
lum_enrich_res = genes_vec_enrichment(genes = top_lum,background = rownames(acc1_cancer_cells),homer = T,title = "lum top enrichment",custom_pathways = luminal_gs)

lum_enrich_res

8.3.3 top correlated score

calculate_score(dataset = acc1_cancer_cells,myo_genes = top_myo,lum_genes = top_lum,lum_threshold = 0,myo_threshold = 0)
correlation of lum score and myo score: -0.05
correlation of lum score and original lum score: 0.58
correlation of myo score and original myo score: 0.77

8.3.4 enriched genes score

rownames(lum_enrich_res) = lum_enrich_res$pathway_name
lum_enriched_genes = lum_enrich_res[1,"geneID"] %>% strsplit(split = "/") %>% .[[1]] %>% c(.,lum_protein_markers) #add original markers
rownames(myo_enrich_res) = myo_enrich_res$pathway_name
myo_enriched_genes = myo_enrich_res[1,"geneID"] %>% strsplit(split = "/") %>% .[[1]] %>% c(.,myo_protein_markers) #add original markers
calculate_score(dataset = acc1_cancer_cells,myo_genes = myo_enriched_genes,lum_genes = lum_enriched_genes,lum_threshold = -2.5,myo_threshold = -2.5)
correlation of lum score and myo score: -0.16
correlation of lum score and original lum score: 0.43
correlation of myo score and original myo score: 0.79

8.4 0.2 Most correlated score

8.4.1 myo Genes

n_vargenes = 2000
myo_protein_markers = c("CNN1", "TP63","ACTA2")
top_myo  = top_correlated(dataset = acc1_cancer_cells, genes = myo_protein_markers,threshold = 0.2,n_vargenes = n_vargenes)
print("Number of genes = " %>% paste(length(top_myo)))
[1] "Number of genes =  48"
message("Names of genes:")
Names of genes:
top_myo %>% head(30)
 [1] "PLOD1"         "RP1-39G22.4"   "PDZK1"         "CSRP1"         "CHI3L1"        "HIST3H3"      
 [7] "AC104699.1"    "ACTG2"         "LYG1"          "DALRD3"        "CD200"         "RP11-627C21.1"
[13] "FGFBP2"        "IGFBP7"        "HSPB3"         "RP11-168A11.4" "SPARC"         "CD83"         
[19] "HLA-DOB"       "TBCC"          "NFKBIE"        "MIR3662"       "SMOC2"         "FBXL6"        
[25] "TPM2"          "SNCG"          "ACTA2"         "DKK3"          "MIR7113"       "CTA-797E19.3" 
message("Genes that also apeared in the original score:")
Genes that also apeared in the original score:
base::intersect(top_myo,original_myo_genes) 
[1] "ACTA2" "DKK3"  "TAGLN"
myo_enrich_res = genes_vec_enrichment(genes = top_myo,background = VariableFeatures(acc1_cancer_cells) %>% head(n_vargenes),homer = T,title = "myo top enrichment",custom_pathways = luminal_gs)

myo_enrich_res

8.4.2 Lum Genes

acc1_cancer_cells = FindVariableFeatures(object = acc1_cancer_cells,nfeatures = 15000)
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
lum_protein_markers = c("KIT")
n_vargenes = 2000
top_lum  = top_correlated(dataset = acc1_cancer_cells, genes = lum_protein_markers,threshold = 0.3,n_vargenes = n_vargenes)
print("Number of genes = " %>% paste(length(top_lum)))
[1] "Number of genes =  13"
message("Names of genes:")
Names of genes:
top_lum %>% head(30)
 [1] "CSDE1"   "RRP9"    "TKT"     "TFG"     "ATP1B3"  "EFNA5"   "GABRP"   "CALML5"  "MMP7"    "SNORD68"
[11] "APP"     "SDF2L1"  "SAT1"   
message("Genes that also apeared in the original score:")
Genes that also apeared in the original score:
base::intersect(top_lum,original_lum_genes) 
character(0)
lum_enrich_res = genes_vec_enrichment(genes = top_lum,background = VariableFeatures(acc1_cancer_cells) %>% head(n_vargenes),homer = T,title = "lum top enrichment",custom_pathways = luminal_gs)

lum_enrich_res
calculate_score(dataset = acc1_cancer_cells,myo_genes = top_myo,lum_genes = top_lum,lum_threshold = 2,myo_threshold = 1)
correlation of lum score and myo score: -0.02
correlation of lum score and original lum score: 0.65
correlation of myo score and original myo score: 0.77

myo_intersected = intersect(top_myo,original_myo_genes) 
lum_intersected = intersect(top_lum,original_lum_genes) 
message("genes in myo score:")
genes in myo score:
myo_intersected
[1] "ACTA2" "DKK3"  "TAGLN"
message("genes in lum score:")
genes in lum score:
lum_intersected
[1] "LGALS3"
calculate_score(dataset = acc1_cancer_cells,myo_genes = myo_intersected,lum_genes = lum_intersected,lum_threshold = 2,myo_threshold = 1)
correlation of lum score and myo score: 0.03
correlation of lum score and original lum score: 0.69
correlation of myo score and original myo score: 0.81

8.4.3 enriched genes

rownames(lum_enrich_res) = lum_enrich_res$pathway_name
lum_enriched_genes = lum_enrich_res[3,"geneID"] %>% strsplit(split = "/") %>% .[[1]] %>% c(.,lum_protein_markers) #add original markers
rownames(myo_enrich_res) = myo_enrich_res$pathway_name
myo_enriched_genes = myo_enrich_res[3,"geneID"] %>% strsplit(split = "/") %>% .[[1]] %>% c(.,myo_protein_markers) #add original markers
message("genes in myo score:")
genes in myo score:
myo_enriched_genes
 [1] "FBLIM1"  "NEXN"    "NMNAT2"  "MYLK"    "CCDC50"  "IGFBP7"  "RAI14"   "ARAP3"   "SPARC"   "CALD1"   "LOXL2"  
[12] "COL5A1"  "ACTA2"   "DKK3"    "MSRB3"   "COL4A1"  "ACTN1"   "TPM1"    "TGFB1I1" "ADORA2B" "MXRA7"   "CNN1"   
[23] "TP63"    "ACTA2"  
message("genes in lum score:")
genes in lum score:
lum_enriched_genes
 [1] "PADI2"      "PATJ"       "PEX11B"     "APH1A"      "C1orf43"    "EFNA4"      "NECTIN4"    "SCYL3"      "ELF3"      
[10] "SOX13"      "IRF6"       "MED28"      "EPB41L4A"   "RGL2"       "C6orf132"   "TPD52L1"    "ICA1"       "MACC1"     
[19] "TRPS1"      "FAM83H"     "RASEF"      "ARRDC1"     "COMMD3"     "ANK3"       "GSTO2"      "PDCD4"      "EHF"       
[28] "ALDH3B2"    "SHANK2"     "SORL1"      "FKBP4"      "PTPN6"      "DUSP16"     "RERG"       "ADCY6"      "ERBB3"     
[37] "ERP29"      "SUSD6"      "RPS6KA5"    "SPINT1"     "FEM1B"      "TLE3"       "SCAMP2"     "CLN3"       "ADGRG1"    
[46] "ATP2C2"     "GGT6"       "MYO1D"      "ST6GALNAC2" "CYB5A"      "BLVRB"      "VRK3"       "SYCP2"      "TMPRSS2"   
[55] "LIMK2"      "KIT"       
calculate_score(dataset = acc1_cancer_cells,myo_genes = myo_enriched_genes,lum_genes = lum_enriched_genes,lum_threshold = 0,myo_threshold = -1)
correlation of lum score and myo score: 0.1
correlation of lum score and original lum score: 0.71
correlation of myo score and original myo score: 0.76

8.4.4 enriched genes and in original score

myo_enriched_genes = myo_enriched_genes[myo_enriched_genes %in% original_myo_genes]
lum_enriched_genes = lum_enriched_genes[lum_enriched_genes %in% original_lum_genes]

message("genes in myo score:")
genes in myo score:
myo_enriched_genes
[1] "MYLK"  "ACTA2" "DKK3"  "TP63"  "ACTA2"
message("genes in lum score:")
genes in lum score:
lum_enriched_genes
[1] "EHF" "KIT"
calculate_score(dataset = acc1_cancer_cells,myo_genes = myo_enriched_genes,lum_genes = lum_enriched_genes,lum_threshold = 2,myo_threshold = 2)
correlation of lum score and myo score: -0.07
correlation of lum score and original lum score: 0.62
correlation of myo score and original myo score: 0.77

9 HPV

Only HMSC cancer cells:

HPV33_P3 = fread("./Data/HPV33_P3.txt",col.names = c("plate","reads")) %>% as.data.frame()
HPV33_P3.df = HPV33_P3 %>% mutate(
  plate = gsub(x =HPV33_P3$plate, replacement = "",pattern = "_.*$") 
  %>% gsub(pattern = "-P",replacement = ".P") 
  %>% gsub(pattern = "-",replacement = "_",)
  )
HPV33_P3.df = HPV33_P3.df %>% dplyr::filter(HPV33_P3.df$plate %in% colnames(acc1_cancer_cells))
rownames(HPV33_P3.df)  <- HPV33_P3.df$plate
HPV33_P3.df$plate = NULL


HPV33_P2 = fread("./Data/HPV33_P2.txt",col.names = c("plate","reads")) %>% as.data.frame()
HPV33_P2.df = HPV33_P2 %>% mutate(
  plate = gsub(x =HPV33_P2$plate, replacement = "",pattern = "_.*$") 
  %>% gsub(pattern = "plate2-",replacement = "plate2_",)
  %>% gsub(pattern = "-",replacement = "\\.",)
  )
HPV33_P2.df = HPV33_P2.df %>% dplyr::filter(HPV33_P2.df$plate %in% colnames(acc1_cancer_cells))
rownames(HPV33_P2.df)  <- HPV33_P2.df$plate
HPV33_P2.df$plate = NULL

HPV33 = rbind(HPV33_P3.df,HPV33_P2.df)
acc1_cancer_cells = AddMetaData(object = acc1_cancer_cells,metadata = HPV33,col.name = "HPV33.reads")
FeaturePlot(acc1_cancer_cells,features = "HPV33.reads",max.cutoff = 10)


data = FetchData(object = acc1_cancer_cells,vars = "HPV33.reads")

data = data %>% mutate("0 reads" = if_else(condition = HPV33.reads == 0,true = 1,false = 0))
data = data %>% mutate("1 reads" = if_else(condition = HPV33.reads == 1,true = 1,false = 0))
data = data %>% mutate("2 reads" = if_else(condition = HPV33.reads == 2,true = 1,false = 0))
data = data %>% mutate("3-23 reads" = if_else(condition = HPV33.reads >=3 &HPV33.reads  <24,true = 1,false = 0))
data = data %>% mutate("24+ reads" = if_else(condition = HPV33.reads >=24,true = 1,false = 0))
data = colSums(data[,2:ncol(data)]) %>% as.data.frame()
names(data)[1] = "count"
data = rownames_to_column(data,var = "bin")
data
ggplot(data=data, aes(x=factor(bin,levels = c("0 reads","1 reads","2 reads","3-23 reads","24+ reads")), y=count)) +
  geom_bar(stat="identity", fill="steelblue") + xlab("HPV Reads")+ theme_minimal()+
  geom_text(aes(label=count), vjust=-0.5, color="black", size=3.5)

hpv33_positive = HPV33 %>% dplyr::mutate(hpv33_positive = case_when(reads >= 10 ~ "positive",
                                                                    reads < 10 ~ "negative")
)



hpv33_positive$reads = NULL
acc1_cancer_cells = AddMetaData(object = acc1_cancer_cells,metadata = hpv33_positive)
DimPlot(object = acc1_cancer_cells,group.by  = c("hpv33_positive"),pt.size = 2)

acc1_cancer_cells$plate = acc1_cancer_cells$orig.ident
saveRDS(object = acc1_cancer_cells, file = "./Data/acc1_cancer_cells_15KnCount_V4.RDS")

10 cNMF

library(reticulate)
acc1_cancer_cells = FindVariableFeatures(object = acc1_cancer_cells,nfeatures = nfeatures)
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
from cnmf import cNMF
import numpy as np
nfeatures_name = r.nfeatures_name
name = 'HMSC_cNMF_'+nfeatures_name+'Kvargenes'
outdir = './Data/cNMF'
K_range = np.arange(3,10)
cnmf_obj = cNMF(output_dir=outdir, name=name)
counts_fn='./Data/cNMF/hmsc_expressionData_'+nfeatures_name+'Kvargenes.txt'
tpm_fn = counts_fn ## This is a weird case where because this dataset is not 3' end umi sequencing, we opted to use the TPM matrix as the input matrix rather than the count matrix

cnmf_obj.prepare(counts_fn=counts_fn, components=K_range, seed=14,tpm_fn=tpm_fn)
cnmf_obj.factorize(worker_i=0, total_workers=1)
cnmf_obj.combine()
cnmf_obj.k_selection_plot()

10.1 Save object

# import pickle
# f = open('./Data/cNMF/HMSC_cNMF_'+nfeatures_name+'Kvargenes/cnmf_obj.pckl', 'wb')
# pickle.dump(cnmf_obj, f)
# f.close()

10.2 Load object

from cnmf import cNMF
import pickle
nfeatures = "2K"
f = open('./Data/cNMF/HMSC_cNMF_' + nfeatures+ 'vargenes/cnmf_obj.pckl', 'rb')
cnmf_obj = pickle.load(f)
f.close()
selected_k = 4
density_threshold = 0.1
cnmf_obj.consensus(k=selected_k, density_threshold=density_threshold,show_clustering=True)
/sci/labs/yotamd/lab_share/avishai.wizel/python_envs/miniconda/envs/cnmf_env_6/lib/python3.7/site-packages/scanpy/preprocessing/_simple.py:843: UserWarning: Received a view of an AnnData. Making a copy.
  view_to_actual(adata)
usage_norm, gep_scores, gep_tpm, topgenes = cnmf_obj.load_results(K=selected_k, density_threshold=density_threshold)
gep_scores = py$gep_scores
gep_tpm = py$gep_tpm
all_metagenes= py$usage_norm

10.3 Enrichment analysis by top 200 genes of each program

plt_list = list()
for (i in 1:ncol(gep_scores)) {
  top_genes = gep_scores  %>%  arrange(desc(gep_scores[i])) #sort by score a
  top = head(rownames(top_genes),200) #take top top_genes_num
  res = genes_vec_enrichment(genes = top,background = rownames(gep_scores),homer = T,title = 
                    i,silent = T,return_all = T)
   
  plt_list[[i]] = res$plt
}
gridExtra::grid.arrange(grobs = plt_list)


canonical_pathways = msigdbr(species = "Homo sapiens", category = "C2") %>% dplyr::filter(gs_subcat != "CGP") %>%  dplyr::distinct(gs_name, gene_symbol) 

plt_list = list()
for (i in 1:ncol(gep_scores)) {
  top_genes = gep_scores  %>%  arrange(desc(gep_scores[i])) #sort by score a
  top = head(rownames(top_genes),200) #take top top_genes_num
  res = genes_vec_enrichment(genes = top,background = rownames(gep_scores),homer = T,title = 
                    i,silent = T,return_all = T,custom_pathways = canonical_pathways)
   
  plt_list[[i]] = res$plt
}
gridExtra::grid.arrange(grobs = plt_list)

# lum genes in metagenes
message("lum genes in metagenes")
lum genes in metagenes
for (i in 1:ncol(gep_scores)) {
  top_genes = gep_scores  %>%  arrange(desc(gep_scores[i])) #sort by score a
  top = head(rownames(top_genes),200) #take top top_genes_num
  cat(paste0("metagene ",i,": "))
  print(original_lum_genes[original_lum_genes %in% top])

}
metagene 1: [1] "KRT7" "SLPI"
metagene 2: [1] "CLDN4"
metagene 3: character(0)
metagene 4: [1] "KRT7"   "LGALS3" "LCN2"   "SLPI"  
cat("\n")
# myo genes in metagenes
message("myo genes in metagenes")
myo genes in metagenes
for (i in 1:ncol(gep_scores)) {
  top_genes = gep_scores  %>%  arrange(desc(gep_scores[i])) #sort by score a
  top = head(rownames(top_genes),200) #take top top_genes_num
  cat(paste0("metagene ",i,": "))
  print(original_myo_genes[original_myo_genes %in% top])

}
metagene 1: [1] "KRT14" "ACTA2" "DKK3" 
metagene 2: character(0)
metagene 3: character(0)
metagene 4: character(0)
cat("\n")
notch_genes = c("JAG1","JAG2","NOTCH3","NOTCH2","NOTCH1","DLL1","MYB","HES4","HEY1","HEY2","NRARP")
# notch genes in metagenes
message("myo genes in metagenes")
myo genes in metagenes
for (i in 1:ncol(gep_scores)) {
  top_genes = gep_scores  %>%  arrange(desc(gep_scores[i])) #sort by score a
  top = head(rownames(top_genes),200) #take top top_genes_num
  cat(paste0("metagene ",i,": "))
  print(notch_genes[notch_genes %in% top])

}
metagene 1: character(0)
metagene 2: character(0)
metagene 3: character(0)
metagene 4: character(0)
cat("\n")
plt_list = list()
for (i in 1:ncol(gep_scores)) {
  top_genes = gep_scores  %>%  arrange(desc(gep_scores[i])) #sort by score a
  top = head(rownames(top_genes),10) #take top top_genes_num
  message(paste("program ",i,"top genes:"))
  print(top)

}
program  1 top genes:
 [1] "IGKV5-2" "NDUFB7"  "LGALS1"  "UBL5"    "S100A6"  "S100A11" "CUTA"    "IFITM3"  "JTB"     "IL17RB" 
program  2 top genes:
 [1] "EGR1"    "C6orf62" "JUNB"    "DNAJA1"  "ATF3"    "IER2"    "ERRFI1"  "KLF6"    "CDKN1A"  "MTHFD2" 
program  3 top genes:
 [1] "RP1-128M12.3"  "RP11-374F3.3"  "RP11-403A21.3" "RP11-454L9.2"  "AC097500.1"    "RP11-463H24.4" "RP11-515O17.2"
 [8] "RP11-536L3.4"  "PALD1"         "AL049758.2"   
program  4 top genes:
 [1] "LTF"           "PIGR"          "FMO2"          "HSD17B2"       "MLPH"          "PRR15L"        "RF00019.219"  
 [8] "RP11-817J15.2" "CD14"          "CLU"          

meta3 = FetchData(object = acc1_cancer_cells,vars = c("metagene.3"))
ggplot(meta3, aes(x=metagene.3)) + 
  geom_density()

meta3[,1] = as.numeric(meta3[,1])
sum(meta3[,1]>0,na.rm = T )
[1] 82
sum(meta3[,1]==0,na.rm = T )
[1] 53

10.4 assignment UMAP

larger_by = 2
message(paste("larger_by = ", larger_by))
larger_by =  2
acc1_cancer_cells = program_assignment(dataset = acc1_cancer_cells,larger_by = larger_by,program_names = colnames(all_metagenes))
selected_k =4
colors =  rainbow(selected_k)
colors = c(colors,"grey")
DimPlot(acc1_cancer_cells,group.by = "program.assignment",pt.size = 2,cols =colors)

show cell cycle program:

hallmark_name = "GO_MITOTIC_CELL_CYCLE"
genesets  =GSEABase::getGmt("./Data/h.all.v7.0.symbols.pluscc.gmt")
var_features=acc1_cancer_cells@assays$RNA@var.features
geneIds= genesets[[hallmark_name]]@geneIds
score <- apply(acc1_cancer_cells@assays$RNA@data[intersect(geneIds,var_features),],2,mean)
acc1_cancer_cells=AddMetaData(acc1_cancer_cells,score,hallmark_name)
FeaturePlot(object = acc1_cancer_cells,features = hallmark_name)

cc_vs_program2 = FetchData(object = acc1_cancer_cells,vars = c("metagene.2",hallmark_name))
cor(cc_vs_program2[1],cc_vs_program2[2])
           GO_MITOTIC_CELL_CYCLE
metagene.2             0.6127281

10.5 Comparisions

cnv_vs_hpv = FetchData(object = acc1_cancer_cells,vars = c("cnv.cluster","hpv33_positive"))
test <- fisher.test(table(cnv_vs_hpv))
ggbarstats(
  cnv_vs_hpv, cnv.cluster, hpv33_positive,
  results.subtitle = FALSE,
  subtitle = paste0(
    "Fisher's exact test", ", p-value = ",
    ifelse(test$p.value < 0.001, "< 0.001", round(test$p.value, 3))
  )
)
cnv_vs_cnmf = FetchData(object = acc1_cancer_cells,vars = c("program.assignment","cnv.cluster"))
cnv_vs_cnmf = cnv_vs_cnmf %>% dplyr::filter(program.assignment == "1" |program.assignment == "2" )
test <- fisher.test(table(cnv_vs_cnmf))
ggbarstats(
  cnv_vs_cnmf, program.assignment, cnv.cluster,
  results.subtitle = FALSE,
  subtitle = paste0(
    "Fisher's exact test", ", p-value = ",
    ifelse(test$p.value < 0.001, "< 0.001", round(test$p.value, 3))
  )
)
cnmf_vs_hpv = FetchData(object = acc1_cancer_cells,vars = c("program.assignment","hpv33_positive"))
cnmf_vs_hpv = cnmf_vs_hpv %>% dplyr::filter(program.assignment == "1" |program.assignment == "2" )
test <- fisher.test(table(cnmf_vs_hpv))
ggbarstats(
  cnmf_vs_hpv, program.assignment, hpv33_positive,
  results.subtitle = FALSE,
  subtitle = paste0(
    "Fisher's exact test", ", p-value = ",
    ifelse(test$p.value < 0.001, "< 0.001", round(test$p.value, 3))
  )
)
myb_vs_cnv = FetchData(object = acc1_cancer_cells,vars = c("cnv.cluster","MYB"))
myb_vs_cnv $cnv.cluster = as.character(myb_vs_cnv $cnv.cluster )

ggboxplot(myb_vs_cnv, x = "cnv.cluster", y = "MYB",
          palette = "jco",
          add = "jitter")+ stat_compare_means(method = "wilcox.test",comparisons = list(c("1","2")))
myb_vs_hpv = FetchData(object = acc1_cancer_cells,vars = c("hpv33_positive","MYB"))
myb_vs_hpv $hpv33_positive = as.character(myb_vs_hpv $hpv33_positive )

ggboxplot(myb_vs_hpv, x = "hpv33_positive", y = "MYB",
          palette = "jco",
          add = "jitter")+ stat_compare_means(method = "wilcox.test",comparisons = list(c("positive","negative")))+ stat_summary(fun.data = function(x) data.frame(y=15, label = paste("Mean=",round(mean(x),digits = 2))), geom="text") +ylab("log2(MYB)")

plate_1_new = subset(acc1_cancer_cells,subset = orig.ident == "ACC.plate2")
myb_vs_hpv = FetchData(object = plate_1_new,vars = c("hpv33_positive","MYB"))
myb_vs_hpv $hpv33_positive = as.character(myb_vs_hpv $hpv33_positive )

# myb_vs_hpv$MYB = 2**myb_vs_hpv$MYB

p = ggboxplot(myb_vs_hpv, x = "hpv33_positive", y = "MYB",
          palette = "jco",
          add = "jitter")+ stat_compare_means(method = "wilcox.test",comparisons = list(c("positive","negative")))+ stat_summary(fun.data = function(x) data.frame(y=15, label = paste("Mean=",round(mean(x),digits = 2))), geom="text") +ylab("log2(MYB)")+ggtitle("ACC.plate2")


plate_2_new = subset(acc1_cancer_cells,subset = orig.ident == "ACC1.P3")
myb_vs_hpv = FetchData(object = plate_2_new,vars = c("hpv33_positive","MYB"))
myb_vs_hpv $hpv33_positive = as.character(myb_vs_hpv $hpv33_positive )
# myb_vs_hpv$MYB = 2**myb_vs_hpv$MYB

p+
ggboxplot(myb_vs_hpv, x = "hpv33_positive", y = "MYB",
          palette = "jco",
          add = "jitter")+ stat_compare_means(method = "wilcox.test",comparisons = list(c("positive","negative")))+ stat_summary(fun.data = function(x) data.frame(y=15, label = paste("Mean=",round(mean(x),digits = 2))), geom="text") +ylab("log2(MYB)")+ggtitle("ACC1.P3")
Warning in wilcox.test.default(c(4.76973518359805, 7.43610462068823, 4.9899976998433,  :
  cannot compute exact p-value with ties

hpvReads_vs_myb = FetchData(object = acc1_cancer_cells,vars = c("HPV33.reads","MYB"))
corr = cor(hpvReads_vs_myb$HPV33.reads,hpvReads_vs_myb$MYB)
print("correlation of MYB abd hpv33_reads:" %>% paste(corr %>% round(digits = 2)))

11 Plate bias

acc1_cancer_cells_data = acc1_cancer_cells@assays[["RNA"]]@data %>% as.data.frame()
acc1_cancer_cells_data = cor(acc1_cancer_cells_data)
annotation = FetchData(object = acc1_cancer_cells,vars = c("orig.ident"))

colors <- c(seq(-1,1,by=0.01))
  my_palette <- c("blue",colorRampPalette(colors = c("blue", "white", "red"))
                                                   (n = length(colors)-3), "red")
  
pht1 = pheatmap(acc1_cor,annotation_col  = annotation,fontsize = 6,breaks = colors, color = my_palette,show_colnames = F,show_rownames = F)

acc1_cancer_cells_data = acc1_cancer_cells@assays[["RNA"]]@data %>% as.data.frame()
acc1_cancer_cells_data = cor(acc1_cancer_cells_data)
annotation = FetchData(object = acc1_cancer_cells,vars = c("cnv.cluster"))

colors <- c(seq(-1,1,by=0.01))
  my_palette <- c("blue",colorRampPalette(colors = c("blue", "white", "red"))
                                                   (n = length(colors)-3), "red")
  
pht1 = pheatmap(acc1_cor,annotation_col  = annotation,fontsize = 6,breaks = colors, color = my_palette,show_colnames = F,show_rownames = F)
cnv_vs_plate = FetchData(object = acc1_cancer_cells,vars = c("cnv.cluster","orig.ident"))
test <- fisher.test(table(cnv_vs_plate))
ggbarstats(
  cnv_vs_plate, cnv.cluster, orig.ident,
  results.subtitle = FALSE,
  subtitle = paste0(
    "Fisher's exact test", ", p-value = ",
    ifelse(test$p.value < 0.001, "< 0.001", round(test$p.value, 3))
  )
)
# creat colours for each group
cnv_vs_plate = FetchData(object = acc1_cancer_cells,vars = c("cnv.cluster","orig.ident","genes_detected"))
cnv_vs_plate$genes_detected[cnv_vs_plate$genes_detected>8000] = 8000
rownames(cnv_vs_plate) = rownames(cnv_vs_plate) %>% gsub(pattern = "_",replacement = "\\.")
cnv_vs_plate$cnv.cluster = as.character(cnv_vs_plate$cnv.cluster)
cnv_vs_plate = cnv_vs_plate %>% dplyr::rename(plate = "orig.ident")
cnv_vs_plate = cnv_vs_plate %>% arrange(plate,genes_detected)
infercnv.observations2_ordered <- infercnv.observations2[match(rownames(cnv_vs_plate), rownames(infercnv.observations2) ),]

annoCol <- list(plate = c(ACC1.P3 = "red",ACC.plate2 = "green"),cnv.cluster =c("1"="green","2" = "red"))

pheatmap(infercnv.observations2_ordered,cluster_cols = F,cluster_rows = F, show_rownames = F,show_colnames = F, breaks = breaks,color = colorRampPalette(rev(c("darkred", "white", "darkblue")))(15),annotation_row = cnv_vs_plate,annotation_colors = annoCol)

# creat colours for each group
cnv_vs_plate = FetchData(object = acc1_cancer_cells,vars = c("cnv.cluster","orig.ident"))

rownames(cnv_vs_plate) = rownames(cnv_vs_plate) %>% gsub(pattern = "_",replacement = "\\.")
cnv_vs_plate$cnv.cluster = as.character(cnv_vs_plate$cnv.cluster)
cnv_vs_plate = cnv_vs_plate %>% dplyr::rename(plate = "orig.ident")
annoCol <- list(plate = c(ACC1.P3 = "red",ACC.plate2 = "green"),cnv.cluster =c("1"="green","2" = "red"))

pheatmap(infercnv.observations2,cluster_cols = F,cluster_rows = F, show_rownames = F,show_colnames = F, breaks = breaks,color = colorRampPalette(rev(c("darkred", "white", "darkblue")))(15),annotation_row = cnv_vs_plate,annotation_colors = annoCol)

data = FetchData(object = acc1_cancer_cells,vars = c("metagene.1","metagene.2"))
# data$genes_detected = min_max_normalize(data$genes_detected)
annotation = FetchData(object = acc1_cancer_cells,vars = c("genes_detected","program.assignment","orig.ident"))
annotation = annotation %>% dplyr::rename(plate = "orig.ident")
annotation$genes_detected[annotation$genes_detected>8000] = 8000
annotation = annotation %>% arrange(plate,genes_detected)
data <- data[match(rownames(annotation), rownames(data) ),]
annoCol <- list(program.assignment = c(metagene.1 = "red",metagene.2 = "grey96",metagene.3 = "yellow",metagene.4 = "blue","NA" = "grey"),plate = c(ACC1.P3 = "red",ACC.plate2 = "green"))

colors <- c(seq(-1,1,by=0.01))
  my_palette <- c("blue",colorRampPalette(colors = c("blue", "white", "red"))
                  (n = length(colors)-3), "red")
  
pheatmap(data,cluster_cols = F,cluster_rows = F,show_rownames = F,color = my_palette, breaks = colors,annotation_row = annotation,annotation_colors = annoCol)
Warning in grSoftVersion() :
  unable to load shared object '/usr/local/lib/R/modules//R_X11.so':
  libXt.so.6: cannot open shared object file: No such file or directory

plate_3 = cnmf_vs_plate %>% dplyr::filter((program.assignment == 1 & orig.ident == "ACC1.P3") ) %>% rownames() 
plate_2 = cnmf_vs_plate %>% dplyr::filter((program.assignment == 2 & orig.ident == "ACC.plate2")) %>% rownames()
cells = list(ACC1.P3 = plate_3,ACC.plate2  = plate_2)

11.1 Results

11.1.1 exceptions

exceptions_plt = DimPlot(object = acc1_cancer_cells, cells.highlight = cells, cols.highlight = c("green","red"), cols = "gray", order = TRUE,pt.size = 2,sizes.highlight = 2,combine = F) 

Warning messages: 1: No Python documentation found for ‘cnmf_obj.prepare’. 2: No Python documentation found for ‘cnmf_obj.prepare’.

colors = c("green","red","cyan","purple","grey")
program.assignment_plt = DimPlot(acc1_cancer_cells,group.by = "program.assignment",pt.size = 2,cols = colors,combine = F)
metagene.1_plt <- FeaturePlot(object = acc1_cancer_cells,features = c("metagene.1"),combine = F)
metagene.2_plt = FeaturePlot(object = acc1_cancer_cells,features = c("metagene.2"),combine = F)

lst = list(exceptions = exceptions_plt, program.assignment = program.assignment_plt,metagene.1 = metagene.1_plt,metagene.2 = metagene.2_plt)

for (i in 1:length(lst)) {
  cat("### ",names(lst)[i]," \n")
  print(
    lst[[i]]
    )
  plot.new()
  dev.off()
  cat(' \n\n')
}

11.1.2 exceptions

[[1]] Warning in grSoftVersion() : unable to load shared object ‘/usr/local/lib/R/modules//R_X11.so’: libXt.so.6: cannot open shared object file: No such file or directory

11.1.3 program.assignment

[[1]]

11.1.4 metagene.1

[[1]]

11.1.5 metagene.2

[[1]]

NA

LS0tCnRpdGxlOiAiVGl0bGUiCmF1dGhvcjogIkF2aXNoYWkgV2l6ZWwiCmRhdGU6ICdgciBTeXMudGltZSgpYCcKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19jb2xsYXBzZTogeWVzCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IEZBTFNFCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRvY19kZXB0aDogMQotLS0KCgojIERhdGEKCmBgYHtyfQphY2MxX2NhbmNlcl9jZWxscyA9IHJlYWRSRFMoIi4vRGF0YS9hY2MxX2NhbmNlcl9jZWxsc18xNUtuQ291bnRfVjMuUkRTIikKYWxsX2FjY19jYW5jZXJfY2VsbHMgPSByZWFkUkRTKCIuL0RhdGEvYWNjX2NhbmNlcl9jZWxsc19WNC5SRFMiKQphY2NfYWxsX2NlbGxzID0gcmVhZFJEUygiLi9EYXRhL2FjY190cG1fbkNvdW50X21pdG9fbm8xNDZfMTVrX3dpdGhfQUNDMV8uUkRTIikKYWNjX2NhbmNlckNlbGxzX25vQUNDMSA9IHJlYWRSRFMoIi4vRGF0YS9hY2NfY2FuY2VyX25vMTQ2X3ByaW1hcnlvbmx5MTVrX2NhbmNlcmNlbGxzLnJkcyIpCgpsdW1pbmFsX3BhdGh3YXlzID0gYygiQ0hBUkFGRV9CUkVBU1RfQ0FOQ0VSX0xVTUlOQUxfVlNfQkFTQUxfRE4iLCJDSEFSQUZFX0JSRUFTVF9DQU5DRVJfTFVNSU5BTF9WU19CQVNBTF9VUCIsIkNIQVJBRkVfQlJFQVNUX0NBTkNFUl9MVU1JTkFMX1ZTX01FU0VOQ0hZTUFMX0ROIiwiQ0hBUkFGRV9CUkVBU1RfQ0FOQ0VSX0xVTUlOQUxfVlNfTUVTRU5DSFlNQUxfVVAiLCJIVVBFUl9CUkVBU1RfQkFTQUxfVlNfTFVNSU5BTF9ETiIsIkxJTV9NQU1NQVJZX0xVTUlOQUxfUFJPR0VOSVRPUl9VUCIsIlNNSURfQlJFQVNUX0NBTkNFUl9MVU1JTkFMX0JfVVAiICkKCiMgYWRkIGx1bWluYWwgcGF0aHdheXN4IApsdW1pbmFsX2dzID0gbXNpZ2RicihzcGVjaWVzID0gIkhvbW8gc2FwaWVucyIpICU+JWFzLmRhdGEuZnJhbWUoKSAlPiUgZHBseXI6OmZpbHRlcihnc19uYW1lICVpbiUgbHVtaW5hbF9wYXRod2F5cyklPiUgZHBseXI6OmRpc3RpbmN0KGdzX25hbWUsIGdlbmVfc3ltYm9sKSAlPiUgYXMuZGF0YS5mcmFtZSgpCgpgYGAKCiMgUGFyYW1ldGVycwoKYGBge3Igd2FybmluZz1GQUxTRX0KYGBgCgoKIyBmdW5jdGlvbnMKCmBgYHtyIHdhcm5pbmc9RkFMU0V9CnNvdXJjZV9mcm9tX2dpdGh1YihyZXBvc2l0b3kgPSAiREVHX2Z1bmN0aW9ucyIsdmVyc2lvbiA9ICIwLjIuMjQiKQpzb3VyY2VfZnJvbV9naXRodWIocmVwb3NpdG95ID0gIkhNU0NfZnVuY3Rpb25zIix2ZXJzaW9uID0gIjAuMS4xMyIsc2NyaXB0X25hbWUgPSAiZnVuY3Rpb25zLlIiKQpzb3VyY2VfZnJvbV9naXRodWIocmVwb3NpdG95ID0gImNOTUZfZnVuY3Rpb25zIix2ZXJzaW9uID0gIjAuMy43MiIsc2NyaXB0X25hbWUgPSAiY25tZl9mdW5jdGlvbl9IYXJtb255LlIiKQpgYGAKIyBVTUFQCmBgYHtyIH0KRGltUGxvdChvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyxwdC5zaXplID0gMikKYGBgCmBgYHtyfQoKZGVnID0gRmluZEFsbE1hcmtlcnMob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsZmVhdHVyZXMgPSBWYXJpYWJsZUZlYXR1cmVzKGFjYzFfY2FuY2VyX2NlbGxzKSxkZW5zaWZ5ID0gVCkKZm9yIChjbHVzdGVyIGluIHVuaXF1ZShkZWckY2x1c3RlcikpIHsKICBwcmludF90YWIocGx0ID0gZGVnW2RlZyRjbHVzdGVyID09IGNsdXN0ZXIsXSwKICAgICAgICAgICAgICApCn0KYGBgCmBgYHtyfQpmb3IgKGNsdXN0ZXIgaW4gdW5pcXVlKGRlZyRjbHVzdGVyKSkgewogIGRlZ19vZl9jbHVzdGVyID0gZGVnW2RlZyRjbHVzdGVyID09IGNsdXN0ZXIsXQogIGVucmljaG1lbnRfYW5hbHlzaXMoZGVnX29mX2NsdXN0ZXIsYmFja2dyb3VuZCA9VmFyaWFibGVGZWF0dXJlcyhhY2MxX2NhbmNlcl9jZWxscyksZmRyX0N1dG9mZiA9IDAuMDEsaWRlbnQuMSA9IHBhc3RlKCJDbHVzdGVyIixjbHVzdGVyKSxpZGVudC4yID0gIHBhc3RlKCJDbHVzdGVyIixjbHVzdGVyKSxzaG93X2J5ID0gMSkKfQoKCmBgYAoKIyMgZmVhdHVyZXMgVU1BUApgYGB7ciBmaWcud2lkdGg9MTB9CkZlYXR1cmVQbG90KG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLGZlYXR1cmVzID0gYygiVFA2MyIsIkFDVEEyIiwiSUwxMkIiLCJDTk4xIikpCmBgYAoKCiMgRW5yaWNobWVudCBhbmFseXNpcyBITVNDIHZzIEFDQwpgYGB7ciBmaWcud2lkdGg9OCwgZWNobz1UUlVFLHJlc3VsdHM9J2hpZGUnLGZpZy5rZWVwPSdhbGwnfQphbGxfYWNjX2NhbmNlcl9jZWxscyA9IFNldElkZW50KGFsbF9hY2NfY2FuY2VyX2NlbGxzLCB2YWx1ZSA9InBhdGllbnQuaWRlbnQiKQphY2NfZGVnIDwtIEZpbmRNYXJrZXJzKGFsbF9hY2NfY2FuY2VyX2NlbGxzLCBpZGVudC4xID0gIkhNU0MiLGxvZ2ZjLnRocmVzaG9sZCA9IDEuNSxmZWF0dXJlcyA9IFZhcmlhYmxlRmVhdHVyZXMoYWxsX2FjY19jYW5jZXJfY2VsbHMpKQplbnJpY2htZW50X2FuYWx5c2lzKGFjY19kZWcsYmFja2dyb3VuZCA9IFZhcmlhYmxlRmVhdHVyZXMoYWxsX2FjY19jYW5jZXJfY2VsbHMpLGZkcl9DdXRvZmYgPSAwLjAxLGlkZW50LjEgPSAiSE1TQyIsaWRlbnQuMiA9ICJBQ0MiLHNob3dfYnkgPSAxKQpgYGAKCiMjIGNlbGwgY3ljbGUgZmlsdGVyaW5nIHsudGFic2V0fQoKYGBge3J9CmhhbGxtYXJrX25hbWUgPSAiR09fTUlUT1RJQ19DRUxMX0NZQ0xFIgpnZW5lc2V0cyAgPWdldEdtdCgiLi9EYXRhL2guYWxsLnY3LjAuc3ltYm9scy5wbHVzY2MuZ210IikKdmFyX2ZlYXR1cmVzPWFjY19jYW5jZXJDZWxsc19ub0FDQzFAYXNzYXlzJFJOQUB2YXIuZmVhdHVyZXMKZ2VuZUlkcz0gZ2VuZXNldHNbW2hhbGxtYXJrX25hbWVdXUBnZW5lSWRzCnNjb3JlIDwtIGFwcGx5KGFjY19jYW5jZXJDZWxsc19ub0FDQzFAYXNzYXlzJFJOQUBzY2FsZS5kYXRhW2ludGVyc2VjdChnZW5lSWRzLHZhcl9mZWF0dXJlcyksXSwyLG1lYW4pCmFjY19jYW5jZXJDZWxsc19ub0FDQzE9QWRkTWV0YURhdGEoYWNjX2NhbmNlckNlbGxzX25vQUNDMSxzY29yZSxoYWxsbWFya19uYW1lKQoKaGFsbG1hcmtfbmFtZSA9ICJHT19NSVRPVElDX0NFTExfQ1lDTEUiCmdlbmVzZXRzICA9Z2V0R210KCIuL0RhdGEvaC5hbGwudjcuMC5zeW1ib2xzLnBsdXNjYy5nbXQiKQp2YXJfZmVhdHVyZXM9YWNjMV9jYW5jZXJfY2VsbHNAYXNzYXlzJFJOQUB2YXIuZmVhdHVyZXMKZ2VuZUlkcz0gZ2VuZXNldHNbW2hhbGxtYXJrX25hbWVdXUBnZW5lSWRzCnNjb3JlIDwtIGFwcGx5KGFjYzFfY2FuY2VyX2NlbGxzQGFzc2F5cyRSTkFAc2NhbGUuZGF0YVtpbnRlcnNlY3QoZ2VuZUlkcyx2YXJfZmVhdHVyZXMpLF0sMixtZWFuKQphY2MxX2NhbmNlcl9jZWxscz1BZGRNZXRhRGF0YShhY2MxX2NhbmNlcl9jZWxscyxzY29yZSxoYWxsbWFya19uYW1lKQoKCiMgaGFsbG1hcmtfbmFtZSA9ICJHT19NSVRPVElDX0NFTExfQ1lDTEUiCiMgZ2VuZXNldHMgID1nZXRHbXQoIi4vRGF0YS9oLmFsbC52Ny4wLnN5bWJvbHMucGx1c2NjLmdtdCIpCiMgdmFyX2ZlYXR1cmVzPWFjYzFfY2FuY2VyX2NlbGxzQGFzc2F5cyRSTkFAdmFyLmZlYXR1cmVzCiMgZ2VuZUlkcz0gZ2VuZXNldHNbW2hhbGxtYXJrX25hbWVdXUBnZW5lSWRzCiMgc2NvcmUgPC0gYXBwbHkoYWNjMV9jYW5jZXJfY2VsbHNAYXNzYXlzJFJOQUBzY2FsZS5kYXRhW2ludGVyc2VjdChnZW5lSWRzLHZhcl9mZWF0dXJlcyksXSwyLG1lYW4pCiMgYWNjMV9jYW5jZXJfY2VsbHM9QWRkTWV0YURhdGEoYWNjMV9jYW5jZXJfY2VsbHMsc2NvcmUsaGFsbG1hcmtfbmFtZSkKCgpgYGAKCmBgYHtyfQpsaWJyYXJ5KGhpZ2hjaGFydGVyKSAKb3B0aW9ucyhoaWdoY2hhcnRlci50aGVtZSA9IGhjX3RoZW1lX3NtcGwodG9vbHRpcCA9IGxpc3QodmFsdWVEZWNpbWFscyA9IDIpKSkKCmNjX3Njb3JlcyA9IEZldGNoRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyx2YXJzID0gIkdPX01JVE9USUNfQ0VMTF9DWUNMRSIpCiBoY2hhcnQoCiAgZGVuc2l0eShjY19zY29yZXMkR09fTUlUT1RJQ19DRUxMX0NZQ0xFKSwgCiAgdHlwZSA9ICJhcmVhIiwgbmFtZSA9ICJHT19NSVRPVElDX0NFTExfQ1lDTEUiCiAgKQoKYGBgCmBgYHtyfQpjY19zY29yZXMgPSBGZXRjaERhdGEob2JqZWN0ID0gYWNjX2NhbmNlckNlbGxzX25vQUNDMSx2YXJzID0gIkdPX01JVE9USUNfQ0VMTF9DWUNMRSIpCiBoY2hhcnQoCiAgZGVuc2l0eShjY19zY29yZXMkR09fTUlUT1RJQ19DRUxMX0NZQ0xFKSwgCiAgdHlwZSA9ICJhcmVhIiwgbmFtZSA9ICJHT19NSVRPVElDX0NFTExfQ1lDTEUiCiAgKQoKYGBgCgoKYGBge3J9CmFjY19jY19zY29yZXMgPSBGZXRjaERhdGEob2JqZWN0ID0gYWNjX2NhbmNlckNlbGxzX25vQUNDMSx2YXJzID0gIkdPX01JVE9USUNfQ0VMTF9DWUNMRSIpCmhtc2NfY2Nfc2NvcmVzID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLHZhcnMgPSAiR09fTUlUT1RJQ19DRUxMX0NZQ0xFIikKCmdncGxvdCgpICsKICBnZW9tX2RlbnNpdHkoYWVzKEdPX01JVE9USUNfQ0VMTF9DWUNMRSwgZmlsbCA9ICJBQ0MiKSwgYWxwaGEgPSAuMiwgZGF0YSA9IGFjY19jY19zY29yZXMpICsKICBnZW9tX2RlbnNpdHkoYWVzKEdPX01JVE9USUNfQ0VMTF9DWUNMRSwgZmlsbCA9ICJITVNDIiksIGFscGhhID0gLjIsIGRhdGEgPSBobXNjX2NjX3Njb3JlcykgKwogIHNjYWxlX2ZpbGxfbWFudWFsKG5hbWUgPSAiRGF0YXNldCIsIHZhbHVlcyA9IGMoQUNDID0gInJlZCIsIEhNU0MgPSAiZ3JlZW4iKSkrIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQ9MC4xNSksCiAgICAgICAgICAgIGNvbG9yPSJibHVlIiwgbGluZXR5cGU9ImRhc2hlZCIsIHNpemU9MSkKCmBgYAoKCgojIyMgQmVmb3JlIGNjIGZpbHRlcmluZwpgYGB7ciB3YXJuaW5nPUZBTFNFfQoKI2ZpbHRlcjoKYWxsX2FjY19jYW5jZXJfY2VsbHNfY2NGaWx0ZXJlZD1hbGxfYWNjX2NhbmNlcl9jZWxsc1ssYWxsX2FjY19jYW5jZXJfY2VsbHNAbWV0YS5kYXRhW1toYWxsbWFya19uYW1lXV08IDAuMTVdCgoKbWluX3RocmVzaG9sZCA9IG1pbihhbGxfYWNjX2NhbmNlcl9jZWxscyRHT19NSVRPVElDX0NFTExfQ1lDTEUpCm1heF90aHJlc2hvbGQgPSBtYXgoYWxsX2FjY19jYW5jZXJfY2VsbHMkR09fTUlUT1RJQ19DRUxMX0NZQ0xFKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KHZpcmlkaXMpCkZlYXR1cmVQbG90KG9iamVjdCA9IGFsbF9hY2NfY2FuY2VyX2NlbGxzLGZlYXR1cmVzID0gaGFsbG1hcmtfbmFtZSkgKyBnZ3RpdGxlKCJCZWZvcmUgY2MgZmlsdGVyaW5nIikgICYgc2NhbGVfY29sb3JfZ3JhZGllbnRuKGNvbG91cnMgPSBwbGFzbWEobiA9IDEwLCBkaXJlY3Rpb24gPSAtMSksIGxpbWl0cyA9IGMobWluX3RocmVzaG9sZCwgbWF4X3RocmVzaG9sZCkpCmBgYAoKCiMjIyBBZnRlciBjYyBmaWx0ZXJpbmcKCmBgYHtyfQpGZWF0dXJlUGxvdChvYmplY3QgPSBhbGxfYWNjX2NhbmNlcl9jZWxsc19jY0ZpbHRlcmVkLGZlYXR1cmVzID0gaGFsbG1hcmtfbmFtZSkgKyBnZ3RpdGxlKCJBZnRlciBjYyBmaWx0ZXJpbmciKSAmIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvdXJzID0gcGxhc21hKG4gPSAxMCwgZGlyZWN0aW9uID0gLTEpLCBsaW1pdHMgPSBjKG1pbl90aHJlc2hvbGQsIG1heF90aHJlc2hvbGQpKQpgYGAKCgoKIyMgey19CgoKIyMgRW5yaWNobWVudCBhbmFseXNpcyBmaWx0ZXJlZCBITVNDIHZzIEFDQwpgYGB7ciBmaWcud2lkdGg9OCwgZWNobz1UUlVFLHJlc3VsdHM9J2hpZGUnLGZpZy5rZWVwPSdhbGwnfQpwYXRpZW50LmlkZW50ID0gYWxsX2FjY19jYW5jZXJfY2VsbHNfY2NGaWx0ZXJlZCRwYXRpZW50LmlkZW50ICU+JSBhcy5kYXRhLmZyYW1lKCkKcGF0aWVudC5pZGVudFssMV0gPSBhcy5jaGFyYWN0ZXIocGF0aWVudC5pZGVudFssMV0pCnBhdGllbnQuaWRlbnRbcGF0aWVudC5pZGVudFssMV0gPT0gIkFDQzEiLF0gPSAiSE1TQyIKcGF0aWVudC5pZGVudFssMV0gPSBhcy5mYWN0b3IocGF0aWVudC5pZGVudFssMV0pCmFsbF9hY2NfY2FuY2VyX2NlbGxzX2NjRmlsdGVyZWQgPSBBZGRNZXRhRGF0YShvYmplY3QgPSBhbGxfYWNjX2NhbmNlcl9jZWxsc19jY0ZpbHRlcmVkLG1ldGFkYXRhID0gcGF0aWVudC5pZGVudCxjb2wubmFtZSA9ICJwYXRpZW50LmlkZW50IikKYWxsX2FjY19jYW5jZXJfY2VsbHNfY2NGaWx0ZXJlZCA9IFNldElkZW50KGFsbF9hY2NfY2FuY2VyX2NlbGxzX2NjRmlsdGVyZWQsIHZhbHVlID0icGF0aWVudC5pZGVudCIpCmFjY19kZWcgPC0gRmluZE1hcmtlcnMoYWxsX2FjY19jYW5jZXJfY2VsbHNfY2NGaWx0ZXJlZCwgaWRlbnQuMSA9ICJITVNDIixsb2dmYy50aHJlc2hvbGQgPSAxLjUsZmVhdHVyZXMgPSBWYXJpYWJsZUZlYXR1cmVzKGFsbF9hY2NfY2FuY2VyX2NlbGxzX2NjRmlsdGVyZWQpKQplbnJpY2htZW50X2FuYWx5c2lzKGFjY19kZWcsYmFja2dyb3VuZCA9IFZhcmlhYmxlRmVhdHVyZXMoYWxsX2FjY19jYW5jZXJfY2VsbHNfY2NGaWx0ZXJlZCksZmRyX0N1dG9mZiA9IDAuMDEsaWRlbnQuMSA9ICJITVNDIixpZGVudC4yID0gIkFDQyIsc2hvd19ieSA9IDEpCmBgYAoKIyBNWUIgZXhwcmVzc2lvbgoKCgpgYGB7ciBmaWcud2lkdGg9MTB9CmFsbF9hY2NfY2FuY2VyX2NlbGxzID0gU2V0SWRlbnQob2JqZWN0ID0gYWxsX2FjY19jYW5jZXJfY2VsbHMsdmFsdWUgPSAicGF0aWVudC5pZGVudCIpICNhY3RpdmUgc25uIGdyYXBoCkZlYXR1cmVQbG90KG9iamVjdCA9IGFsbF9hY2NfY2FuY2VyX2NlbGxzLGZlYXR1cmVzID0gIk1ZQiIsbGFiZWwgPSBUKQpgYGAKCmBgYHtyIGZpZy53aWR0aD0xMH0KYWxsX2FjY19jYW5jZXJfY2VsbHMgPSBTZXRJZGVudChvYmplY3QgPSBhbGxfYWNjX2NhbmNlcl9jZWxscyx2YWx1ZSA9ICJwYXRpZW50LmlkZW50IikgI2FjdGl2ZSBzbm4gZ3JhcGgKRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWxsX2FjY19jYW5jZXJfY2VsbHMsZmVhdHVyZXMgPSAiTVlCIixsYWJlbCA9IFQpCmBgYAoKIyBDTlYgey50YWJzZXR9CgoKCmBgYHtyfQojc2V0IGNlbGwgdHlwZXMKbmV3LmNsdXN0ZXIuaWRzIDwtIGMoImNhbmNlciIsICMwCiAgICAgICAgICAgICAgICAgICAgICJjYW5jZXIiLCAjMQogICAgICAgICAgICAgICAgICAgICAiQ0FGIiwgIzIKICAgICAgICAgICAgICAgICAgICAgImNhbmNlciIsICMzCiAgICAgICAgICAgICAgICAgICAgICJFbmRvdGhlbGlhbCIsICM0CiAgICAgICAgICAgICAgICAgICAgICJjYW5jZXIiLCAjNQogICAgICAgICAgICAgICAgICAgICAiY2FuY2VyIiwgIzYKICAgICAgICAgICAgICAgICAgICAgIkNBRiIsICM3CiAgICAgICAgICAgICAgICAgICAgICJDQUYiLCAjOAogICAgICAgICAgICAgICAgICAgICAiQ0FGIiwgIzkKICAgICAgICAgICAgICAgICAgICAgImNhbmNlciIsICMxMAogICAgICAgICAgICAgICAgICAgICAiQ0FGIiwgIzExCiAgICAgICAgICAgICAgICAgICAgICJjYW5jZXIiLCAjMTIKICAgICAgICAgICAgICAgICAgICAgImNhbmNlciIsICMxMwogICAgICAgICAgICAgICAgICAgICAiY2FuY2VyIiwgIzE0CiAgICAgICAgICAgICAgICAgICAgICJjYW5jZXIiLCAjMTUKICAgICAgICAgICAgICAgICAgICAgImNhbmNlciIsICMxNgogICAgICAgICAgICAgICAgICAgICAiV0JDIiwgIzE3CiAgICAgICAgICAgICAgICAgICAgICJDQUYiICMxOAogICAgICAgICAgICAgICAgICAgICApCmBgYAoKCmBgYHtyIGZpZy5zaG93PSdoaWRlJ30KI3JlbmFtZSBpZGVudHM6CmFjY19hbGxfY2VsbHMgPSBTZXRJZGVudChvYmplY3QgPSBhY2NfYWxsX2NlbGxzLHZhbHVlID0gIlJOQV9zbm5fcmVzLjEiKSAjYWN0aXZlIHNubiBncmFwaApuYW1lcyhuZXcuY2x1c3Rlci5pZHMpIDwtIGxldmVscyhhY2NfYWxsX2NlbGxzKSAjYWRkIHNubiBncmFwaCBsZXZlbHMgdG8gbmV3LmNsdXN0ZXIuaWRzCmFjY19hbGxfY2VsbHNAbWV0YS5kYXRhW1sic2V1cmF0X2NsdXN0ZXJzIl1dID0gYWNjX2FsbF9jZWxsc0BtZXRhLmRhdGFbWyJSTkFfc25uX3Jlcy4xIl1dCmFjY19hbGxfY2VsbHMgPSBTZXRJZGVudChvYmplY3QgPSBhY2NfYWxsX2NlbGxzLHZhbHVlID0gInNldXJhdF9jbHVzdGVycyIpCmFjY19hbGxfY2VsbHMgPC0gUmVuYW1lSWRlbnRzKGFjY19hbGxfY2VsbHMsIG5ldy5jbHVzdGVyLmlkcykgCgojIGRpdmlkZSAiY2FuY2VyIiBpbnRvIHBhdGllbnRzOgpjZWxsX3R5cGVzID0gYWNjX2FsbF9jZWxsc0BhY3RpdmUuaWRlbnQgJT4lIGFzLmRhdGEuZnJhbWUoKQpjZWxsX3R5cGVzWywxXTwtIGFzLmNoYXJhY3RlcihjZWxsX3R5cGVzWywxXSkKY2VsbF90eXBlcyA9IGNiaW5kKGNlbGxfdHlwZXMsYWNjX2FsbF9jZWxscyRwYXRpZW50LmlkZW50KSAlPiUgc2V0bmFtZXMob2xkID0gbmFtZXMoLiksIAogICAgICAgICBuZXcgPSBjKCdjZWxsX3R5cGUnLCdwYXRpZW50JykpCmNlbGxfdHlwZXNbY2VsbF90eXBlcyRjZWxsX3R5cGUgPT0gImNhbmNlciIsXSA9IGNlbGxfdHlwZXNbY2VsbF90eXBlcyRjZWxsX3R5cGUgPT0gImNhbmNlciIsMl0KCgojIGhtc2Nfcm93cyA9IChzdGFydHNXaXRoKHggPSByb3duYW1lcyhjZWxsX3R5cGVzKSxwcmVmaXggPSAiQUNDLnBsYXRlMiIpIHwgc3RhcnRzV2l0aCh4ID0gcm93bmFtZXMoY2VsbF90eXBlcykscHJlZml4ID0gIkFDQzEuIikpICYgY2VsbF90eXBlc1ssMV0gPT0gImNhbmNlciIgCiMgYWNjX3Jvd3MgPSAhKHN0YXJ0c1dpdGgoeCA9IHJvd25hbWVzKGNlbGxfdHlwZXMpLHByZWZpeCA9ICJBQ0MucGxhdGUyIikgfCBzdGFydHNXaXRoKHggPSByb3duYW1lcyhjZWxsX3R5cGVzKSxwcmVmaXggPSAiQUNDMS4iKSkgJiBjZWxsX3R5cGVzWywxXSA9PSAiY2FuY2VyIiAKIyBjZWxsX3R5cGVzWywxXVtobXNjX3Jvd3NdICA9ICJITVNDIgojIGNlbGxfdHlwZXNbLDFdW2FjY19yb3dzXSAgPSAiQUNDIgoKI2FkZCB0byBtZXRhZGF0YToKY2VsbF90eXBlc1ssMl0gPSBOVUxMIApjZWxsX3R5cGVzW2NlbGxfdHlwZXMkY2VsbF90eXBlID09ICJBQ0MxIixdID0gIkhNU0MiCmFjY19hbGxfY2VsbHMgPSBBZGRNZXRhRGF0YShvYmplY3QgPWFjY19hbGxfY2VsbHMgLG1ldGFkYXRhID0gY2VsbF90eXBlcyxjb2wubmFtZSA9ICJjZWxsLnR5cGUiKQpgYGAKIyB7LX0KCiMjIENOViBVTUFQIAoKYGBge3IgZmlnLndpZHRoPTEwfQpsaWJyYXJ5KGluZmVyY252KQpsaWJyYXJ5KHRpZHl2ZXJzZSkKYWNjX2Fubm90YXRpb24gID0gYXMuZGF0YS5mcmFtZShhY2NfYWxsX2NlbGxzQG1ldGEuZGF0YVssImNlbGwudHlwZSIsZHJvcCA9IEZdKQphY2NfYW5ub3RhdGlvbiA9IGFjY19hbm5vdGF0aW9uICU+JSByb3duYW1lc190b19jb2x1bW4oIm9yaWcuaWRlbnQiKSAKYWNjX2Fubm90YXRpb24gPSBhY2NfYW5ub3RhdGlvbiAlPiUgbXV0YXRlKG9yaWcuaWRlbnQgPSBnc3ViKHggPSBhY2NfYW5ub3RhdGlvbiRvcmlnLmlkZW50LHBhdHRlcm4gPSAiXFwuIiwgcmVwbGFjZW1lbnQgPSAiLSIpICU+JSAKICBnc3ViKHBhdHRlcm4gPSAiXyIsIHJlcGxhY2VtZW50ID0gIi0iKSkKICAKCndyaXRlLnRhYmxlKGFjY19hbm5vdGF0aW9uLCAiLi9EYXRhL2luZmVyQ05WL2FjY19hbm5vdGF0aW9uLnR4dCIsIGFwcGVuZCA9IEZBTFNFLCAKICAgICAgICAgICAgc2VwID0gIlx0IiwgZGVjID0gIi4iLHJvdy5uYW1lcyA9IEZBTFNFLCBjb2wubmFtZXMgPSBGKQoKaW5mZXJjbnZfb2JqID0gQ3JlYXRlSW5mZXJjbnZPYmplY3QocmF3X2NvdW50c19tYXRyaXg9Ii4vRGF0YS9pbmZlckNOVi9hbGwuNGljbnYudHh0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFubm90YXRpb25zX2ZpbGU9Ii4vRGF0YS9pbmZlckNOVi9hY2NfYW5ub3RhdGlvbi50eHQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxpbT0iXHQiLGdlbmVfb3JkZXJfZmlsZT0iLi9EYXRhL2luZmVyQ05WL2dlbmNvZGVfdjE5X2dlbmVfcG9zLnR4dCIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHJlZl9ncm91cF9uYW1lcz1jKCJDQUYiLCAiRW5kb3RoZWxpYWwiLCAiV0JDIikpICNncm91cHMgb2Ygbm9ybWFsIGNlbGxzCgppbmZlcmNudl9vYmpfZGVmYXVsdCA9IGluZmVyY252OjpydW4oaW5mZXJjbnZfb2JqLCBjdXRvZmY9MSwgb3V0X2Rpcj0nLi9EYXRhL2luZmVyQ05WL2luZmVyY252X291dHB1dCcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbHVzdGVyX2J5X2dyb3Vwcz1ULCBwbG90X3N0ZXBzPUZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVub2lzZT1UUlVFLCBITU09RkFMU0UsIG5vX3ByZWxpbV9wbG90PVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbmdfcmVzPTMwMCkKcGxvdF9jbnYoaW5mZXJjbnZfb2JqX2RlZmF1bHQsIG91dHB1dF9mb3JtYXQgPSAicG5nIiwgIHdyaXRlX2V4cHJfbWF0cml4ID0gRkFMU0Usb3V0X2RpciA9ICIuL0RhdGEvaW5mZXJDTlYvIixwbmdfcmVzCT04MDAsb2JzX3RpdGxlID0gIk1hbGlnbmFudCBjZWxscyIscmVmX3RpdGxlID0gIk5vcm1hbCBjZWxscyIpCgoKY2x1c3Rlci5pbmZvPUZldGNoRGF0YShhY2NfYWxsX2NlbGxzLGMoImlkZW50Iiwib3JpZy5pZGVudCIsIlVNQVBfMSIsIlVNQVBfMiIsIm5Db3VudF9STkEiLCJuRmVhdHVyZV9STkEiLCJwZXJjZW50Lm10IiwicGF0aWVudC5pZGVudCIsInNldXJhdF9jbHVzdGVycyIpKQpjbHVzdGVyLmluZm8kY2VsbD1yb3duYW1lcyhjbHVzdGVyLmluZm8pCgpsaWJyYXJ5KGxpbW1hKQpzbW9vdGhlZD1hcHBseShpbmZlcmNudl9vYmpfZGVmYXVsdEBleHByLmRhdGEsMix0cmljdWJlTW92aW5nQXZlcmFnZSwgc3Bhbj0wLjAxKQpjbnNpZz1zcXJ0KGFwcGx5KChzbW9vdGhlZC0xKV4yLDIsbWVhbikpCnVtYXA9Y2x1c3Rlci5pbmZvCm5hbWVzKGNuc2lnKT11bWFwJGNlbGwKCmFjY19hbGxfY2VsbHMgPC0gQWRkTWV0YURhdGEob2JqZWN0ID0gYWNjX2FsbF9jZWxscywgbWV0YWRhdGEgPSBjbnNpZywgY29sLm5hbWUgPSAiY29weW51bWJlciIpCmFjY19hbGxfY2VsbHMgPSBTZXRJZGVudChvYmplY3QgPSBhY2NfYWxsX2NlbGxzLHZhbHVlID0gImNlbGwudHlwZSIpCkZlYXR1cmVQbG90KGFjY19hbGxfY2VsbHMsICJjb3B5bnVtYmVyIixwdC5zaXplID0gMSwgY29scyA9IGMoImxpZ2h0Ymx1ZSIsIm9yYW5nZSIsInJlZCIsImRhcmtyZWQiKSxsYWJlbCA9IFQscmVwZWwgPSBUKQpgYGAKCmBgYHtyfQphY2NfY2FuY2VyX2NlbGxzIDwtIEFkZE1ldGFEYXRhKG9iamVjdCA9IGFjY19jYW5jZXJfY2VsbHMsIG1ldGFkYXRhID0gY25zaWcsIGNvbC5uYW1lID0gImNvcHludW1iZXIiKQphY2NfY2FuY2VyX2NlbGxzID0gU2V0SWRlbnQob2JqZWN0ID0gYWNjX2NhbmNlcl9jZWxscyx2YWx1ZSA9ICJjZWxsLnR5cGUiKQpGZWF0dXJlUGxvdChhY2NfY2FuY2VyX2NlbGxzLCAiY29weW51bWJlciIscHQuc2l6ZSA9IDEsIGNvbHMgPSBjKCJsaWdodGJsdWUiLCJvcmFuZ2UiLCJyZWQiLCJkYXJrcmVkIiksbGFiZWwgPSBULHJlcGVsID0gVCkKYGBgCgoKIyMgQ05WIHBsb3QgCgohW0NOViBwbG90XSgvc2NpL2xhYnMveW90YW1kL2xhYl9zaGFyZS9hdmlzaGFpLndpemVsL1JfcHJvamVjdHMvSE1TQy9EYXRhL2luZmVyQ05WL2luZmVyY252LnBuZykKCgojIyBDTlYgc3VidHlwZXMKCmBgYHtyfQpjbnZfc3VidHlwZXMgPSBhcy5kYXRhLmZyYW1lKGN1dHJlZShpbmZlcmNudl9vYmpfZGVmYXVsdEB0dW1vcl9zdWJjbHVzdGVyc1tbImhjIl1dW1siSE1TQyJdXSwgayA9IDIpKQpuYW1lcyhjbnZfc3VidHlwZXMpWzFdID0gImNudi5jbHVzdGVyIgpyb3duYW1lcyhjbnZfc3VidHlwZXMpID0gcm93bmFtZXMoY252X3N1YnR5cGVzKSAlPiUgZ3N1YihwYXR0ZXJuID0gIi0iLHJlcGxhY2VtZW50ID0gIlxcLiIpCmNudl9zdWJ0eXBlcyBbLDFdID0gYXMuY2hhcmFjdGVyKGNudl9zdWJ0eXBlc1ssMV0pCmluZmVyY252Lm9ic2VydmF0aW9ucyA9IGRhdGEuZnJhbWUoZnJlYWQoZmlsZSA9ICIuL0RhdGEvaW5mZXJDTlYvaW5mZXJjbnYub2JzZXJ2YXRpb25zLnR4dCIpLCByb3cubmFtZXM9MSkKbmFtZXNfdG9fa2VlcCA9IGNvbG5hbWVzKGluZmVyY252Lm9ic2VydmF0aW9ucykgJWluJSAoY29sbmFtZXMoYWNjMV9jYW5jZXJfY2VsbHMpICU+JSBnc3ViKHBhdHRlcm4gPSAiXyIscmVwbGFjZW1lbnQgPSAiXFwuIikpCmluZmVyY252Lm9ic2VydmF0aW9ucyA9IGluZmVyY252Lm9ic2VydmF0aW9uc1ssbmFtZXNfdG9fa2VlcF0KYGBgCgoKCmBgYHtyfQpyb3RhdGUgPC0gZnVuY3Rpb24oeCkgdChhcHBseSh4LCAyLCByZXYpKQppbmZlcmNudi5vYnNlcnZhdGlvbnMyID0gaW5mZXJjbnYub2JzZXJ2YXRpb25zICU+JSByb3RhdGUoKSAlPiUgIHJvdGF0ZSgpICU+JSByb3RhdGUoKSU+JSBhcy5kYXRhLmZyYW1lKCkgCmJyZWFrcyA9IGMoMC43MDA4OTE4NjE3MDQ4NTcsCjAuNzQyMzY2OTQ1NTI4MzY5LAowLjc4Mzg0MjAyOTM1MTg4MSwKMC44MjUzMTcxMTMxNzUzOTMsCjAuODY2NzkyMTk2OTk4OTA1LAowLjkwODI2NzI4MDgyMjQxNywKMC45NDk3NDIzNjQ2NDU5MjgsCjAuOTkxMjE3NDQ4NDY5NDQsCjEuMDMyNjkyNTMyMjkyOTUsCjEuMDc0MTY3NjE2MTE2NDYsCjEuMTE1NjQyNjk5OTM5OTgsCjEuMTU3MTE3NzgzNzYzNDksCjEuMTk4NTkyODY3NTg3LAoxLjI0MDA2Nzk1MTQxMDUxLAoxLjI4MTU0MzAzNTIzNDAyLAoxLjMyMzAxODExOTA1NzUzKQpwaGVhdG1hcChpbmZlcmNudi5vYnNlcnZhdGlvbnMyLGNsdXN0ZXJfY29scyA9IEYsY2x1c3Rlcl9yb3dzID0gRiwgc2hvd19yb3duYW1lcyA9IEYsc2hvd19jb2xuYW1lcyA9IEYsIGJyZWFrcyA9IGJyZWFrcyxjb2xvciA9IGNvbG9yUmFtcFBhbGV0dGUocmV2KGMoImRhcmtyZWQiLCAid2hpdGUiLCAiZGFya2JsdWUiKSkpKDE1KSxhbm5vdGF0aW9uX3JvdyA9IGNudl9zdWJ0eXBlcykKCmBgYAoKYGBge3J9CnJvd25hbWVzKGNudl9zdWJ0eXBlcykgPSByb3duYW1lcyhjbnZfc3VidHlwZXMpICU+JSBnc3ViKHBhdHRlcm4gPSAiMlxcLiIscmVwbGFjZW1lbnQgPSAiMl8iKQpyb3duYW1lcyhjbnZfc3VidHlwZXMpID0gcm93bmFtZXMoY252X3N1YnR5cGVzKSAlPiUgZ3N1YihwYXR0ZXJuID0gIjNcXC4iLHJlcGxhY2VtZW50ID0gIjNfIikKYWNjMV9jYW5jZXJfY2VsbHMgPSBBZGRNZXRhRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyxtZXRhZGF0YSA9IGNudl9zdWJ0eXBlcykKYGBgCgpgYGB7cn0KRGltUGxvdChhY2MxX2NhbmNlcl9jZWxscyxncm91cC5ieSA9ICJjbnYuY2x1c3RlciIscHQuc2l6ZSA9IDIpCmBgYAojIE15by1MdW0gc2NvcmUKCgoKIyMgT3JpZ2luYWwgc2NvcmUKYGBge3J9Cm9yaWdpbmFsX215b19nZW5lcyA9IGMoICJUUDYzIiwgIlRQNzMiLCAiQ0FWMSIsICJDREgzIiwgIktSVDUiLCAiS1JUMTQiLCAiQUNUQTIiLCAiVEFHTE4iLCAiTVlMSyIsICJES0szIikKb3JpZ2luYWxfbHVtX2dlbmVzID0gYygiS0lUIiwgIkVIRiIsICJFTEY1IiwgIktSVDciLCAiQ0xETjMiLCAiQ0xETjQiLCAiQ0QyNCIsICJMR0FMUzMiLCAiTENOMiIsICJTTFBJIiApCmBgYAoKCgpgYGB7cn0KY2FsY3VsYXRlX3Njb3JlKGRhdGFzZXQgPSBhbGxfYWNjX2NhbmNlcl9jZWxscyxteW9fZ2VuZXMgPSBvcmlnaW5hbF9teW9fZ2VuZXMsbHVtX2dlbmVzID0gb3JpZ2luYWxfbHVtX2dlbmVzKQpgYGAKIyMgT3JpZ2luYWwgc2NvcmUgb2YgQUNDMQoKYGBge3J9CmNhbGN1bGF0ZV9zY29yZShkYXRhc2V0ID0gYWNjMV9jYW5jZXJfY2VsbHMsbXlvX2dlbmVzID0gb3JpZ2luYWxfbXlvX2dlbmVzLGx1bV9nZW5lcyA9IG9yaWdpbmFsX2x1bV9nZW5lcyxsdW1fdGhyZXNob2xkID0gMCxteW9fdGhyZXNob2xkID0gMCkKYGBgCgoKIyMgMC4zNSBNb3N0IGNvcnJlbGF0ZWQgc2NvcmUgey50YWJzZXR9CgojIyMgTXlvIGdlbmVzCgoKYGBge3Igd2FybmluZz1GQUxTRSwgY29sbGFwc2U9VH0KbXlvX3Byb3RlaW5fbWFya2VycyA9IGMoIkNOTjEiLCAiVFA2MyIsIkFDVEEyIikKdG9wX215byAgPSB0b3BfY29ycmVsYXRlZChkYXRhc2V0ID0gYWNjMV9jYW5jZXJfY2VsbHMsIGdlbmVzID0gbXlvX3Byb3RlaW5fbWFya2Vycyx0aHJlc2hvbGQgPSAwLjM1KQpwcmludCgiTnVtYmVyIG9mIGdlbmVzID0gIiAlPiUgcGFzdGUobGVuZ3RoKHRvcF9teW8pKSkKbWVzc2FnZSgiTmFtZXMgb2YgZ2VuZXM6IikKdG9wX215byAlPiUgaGVhZCgzMCkKbWVzc2FnZSgiR2VuZXMgdGhhdCBhbHNvIGFwZWFyZWQgaW4gdGhlIG9yaWdpbmFsIHNjb3JlOiIpCmJhc2U6OmludGVyc2VjdCh0b3BfbXlvLG9yaWdpbmFsX215b19nZW5lcykgCmBgYApgYGB7cn0KbXlvX2VucmljaF9yZXMgPSBnZW5lc192ZWNfZW5yaWNobWVudChnZW5lcyA9IHRvcF9teW8sYmFja2dyb3VuZCA9IHJvd25hbWVzKGFjYzFfY2FuY2VyX2NlbGxzKSxob21lciA9IFQsdGl0bGUgPSAibXlvIHRvcCBlbnJpY2htZW50IixjdXN0b21fcGF0aHdheXMgPSBsdW1pbmFsX2dzKQpteW9fZW5yaWNoX3JlcwpgYGAKIyMjIEx1bSBnZW5lcwpgYGB7cn0KbHVtX3Byb3RlaW5fbWFya2VycyA9IGMoIktJVCIpCnRvcF9sdW0gID0gdG9wX2NvcnJlbGF0ZWQoZGF0YXNldCA9IGFjYzFfY2FuY2VyX2NlbGxzLCBnZW5lcyA9IGx1bV9wcm90ZWluX21hcmtlcnMsdGhyZXNob2xkID0gMC4zNSxuX3ZhcmdlbmVzID0gNTAwMCkKcHJpbnQoIk51bWJlciBvZiBnZW5lcyA9ICIgJT4lIHBhc3RlKGxlbmd0aCh0b3BfbHVtKSkpCm1lc3NhZ2UoIk5hbWVzIG9mIGdlbmVzOiIpCnRvcF9sdW0gJT4lIGhlYWQoMzApCm1lc3NhZ2UoIkdlbmVzIHRoYXQgYWxzbyBhcGVhcmVkIGluIHRoZSBvcmlnaW5hbCBzY29yZToiKQpiYXNlOjppbnRlcnNlY3QodG9wX2x1bSxvcmlnaW5hbF9sdW1fZ2VuZXMpIApgYGAKCmBgYHtyfQpsdW1fZW5yaWNoX3JlcyA9IGdlbmVzX3ZlY19lbnJpY2htZW50KGdlbmVzID0gdG9wX2x1bSxiYWNrZ3JvdW5kID0gcm93bmFtZXMoYWNjMV9jYW5jZXJfY2VsbHMpLGhvbWVyID0gVCx0aXRsZSA9ICJsdW0gdG9wIGVucmljaG1lbnQiLGN1c3RvbV9wYXRod2F5cyA9IGx1bWluYWxfZ3MpCmx1bV9lbnJpY2hfcmVzCmBgYAojIyMgdG9wIGNvcnJlbGF0ZWQgc2NvcmUKYGBge3J9CmNhbGN1bGF0ZV9zY29yZShkYXRhc2V0ID0gYWNjMV9jYW5jZXJfY2VsbHMsbXlvX2dlbmVzID0gdG9wX215byxsdW1fZ2VuZXMgPSB0b3BfbHVtLGx1bV90aHJlc2hvbGQgPSAwLG15b190aHJlc2hvbGQgPSAwKQpgYGAKCgojIyMgIGVucmljaGVkIGdlbmVzIHNjb3JlCmBgYHtyfQpyb3duYW1lcyhsdW1fZW5yaWNoX3JlcykgPSBsdW1fZW5yaWNoX3JlcyRwYXRod2F5X25hbWUKbHVtX2VucmljaGVkX2dlbmVzID0gbHVtX2VucmljaF9yZXNbMSwiZ2VuZUlEIl0gJT4lIHN0cnNwbGl0KHNwbGl0ID0gIi8iKSAlPiUgLltbMV1dICU+JSBjKC4sbHVtX3Byb3RlaW5fbWFya2VycykgI2FkZCBvcmlnaW5hbCBtYXJrZXJzCmBgYAoKYGBge3J9CnJvd25hbWVzKG15b19lbnJpY2hfcmVzKSA9IG15b19lbnJpY2hfcmVzJHBhdGh3YXlfbmFtZQpteW9fZW5yaWNoZWRfZ2VuZXMgPSBteW9fZW5yaWNoX3Jlc1sxLCJnZW5lSUQiXSAlPiUgc3Ryc3BsaXQoc3BsaXQgPSAiLyIpICU+JSAuW1sxXV0gJT4lIGMoLixteW9fcHJvdGVpbl9tYXJrZXJzKSAjYWRkIG9yaWdpbmFsIG1hcmtlcnMKYGBgCgpgYGB7cn0KY2FsY3VsYXRlX3Njb3JlKGRhdGFzZXQgPSBhY2MxX2NhbmNlcl9jZWxscyxteW9fZ2VuZXMgPSBteW9fZW5yaWNoZWRfZ2VuZXMsbHVtX2dlbmVzID0gbHVtX2VucmljaGVkX2dlbmVzLGx1bV90aHJlc2hvbGQgPSAtMi41LG15b190aHJlc2hvbGQgPSAtMi41KQpgYGAKCgojIyB7LX0KCgojIyAgMC4yIE1vc3QgY29ycmVsYXRlZCBzY29yZSB7LnRhYnNldH0KCiMjIyAgbXlvIEdlbmVzCgpgYGB7cn0KCmBgYAoKYGBge3Igd2FybmluZz1GQUxTRX0Kbl92YXJnZW5lcyA9IDIwMDAKbXlvX3Byb3RlaW5fbWFya2VycyA9IGMoIkNOTjEiLCAiVFA2MyIsIkFDVEEyIikKdG9wX215byAgPSB0b3BfY29ycmVsYXRlZChkYXRhc2V0ID0gYWNjMV9jYW5jZXJfY2VsbHMsIGdlbmVzID0gbXlvX3Byb3RlaW5fbWFya2Vycyx0aHJlc2hvbGQgPSAwLjIsbl92YXJnZW5lcyA9IG5fdmFyZ2VuZXMpCnByaW50KCJOdW1iZXIgb2YgZ2VuZXMgPSAiICU+JSBwYXN0ZShsZW5ndGgodG9wX215bykpKQptZXNzYWdlKCJOYW1lcyBvZiBnZW5lczoiKQp0b3BfbXlvICU+JSBoZWFkKDMwKQptZXNzYWdlKCJHZW5lcyB0aGF0IGFsc28gYXBlYXJlZCBpbiB0aGUgb3JpZ2luYWwgc2NvcmU6IikKYmFzZTo6aW50ZXJzZWN0KHRvcF9teW8sb3JpZ2luYWxfbXlvX2dlbmVzKSAKbXlvX2VucmljaF9yZXMgPSBnZW5lc192ZWNfZW5yaWNobWVudChnZW5lcyA9IHRvcF9teW8sYmFja2dyb3VuZCA9IFZhcmlhYmxlRmVhdHVyZXMoYWNjMV9jYW5jZXJfY2VsbHMpICU+JSBoZWFkKG5fdmFyZ2VuZXMpLGhvbWVyID0gVCx0aXRsZSA9ICJteW8gdG9wIGVucmljaG1lbnQiLGN1c3RvbV9wYXRod2F5cyA9IGx1bWluYWxfZ3MpCm15b19lbnJpY2hfcmVzCmBgYAoKIyMjICBMdW0gR2VuZXMKCmBgYHtyfQphY2MxX2NhbmNlcl9jZWxscyA9IEZpbmRWYXJpYWJsZUZlYXR1cmVzKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLG5mZWF0dXJlcyA9IDE1MDAwKQpgYGAKCmBgYHtyfQpsdW1fcHJvdGVpbl9tYXJrZXJzID0gYygiS0lUIikKbl92YXJnZW5lcyA9IDIwMDAKdG9wX2x1bSAgPSB0b3BfY29ycmVsYXRlZChkYXRhc2V0ID0gYWNjMV9jYW5jZXJfY2VsbHMsIGdlbmVzID0gbHVtX3Byb3RlaW5fbWFya2Vycyx0aHJlc2hvbGQgPSAwLjMsbl92YXJnZW5lcyA9IG5fdmFyZ2VuZXMpCnByaW50KCJOdW1iZXIgb2YgZ2VuZXMgPSAiICU+JSBwYXN0ZShsZW5ndGgodG9wX2x1bSkpKQptZXNzYWdlKCJOYW1lcyBvZiBnZW5lczoiKQp0b3BfbHVtICU+JSBoZWFkKDMwKQptZXNzYWdlKCJHZW5lcyB0aGF0IGFsc28gYXBlYXJlZCBpbiB0aGUgb3JpZ2luYWwgc2NvcmU6IikKYmFzZTo6aW50ZXJzZWN0KHRvcF9sdW0sb3JpZ2luYWxfbHVtX2dlbmVzKSAKCmx1bV9lbnJpY2hfcmVzID0gZ2VuZXNfdmVjX2VucmljaG1lbnQoZ2VuZXMgPSB0b3BfbHVtLGJhY2tncm91bmQgPSBWYXJpYWJsZUZlYXR1cmVzKGFjYzFfY2FuY2VyX2NlbGxzKSAlPiUgaGVhZChuX3ZhcmdlbmVzKSxob21lciA9IFQsdGl0bGUgPSAibHVtIHRvcCBlbnJpY2htZW50IixjdXN0b21fcGF0aHdheXMgPSBsdW1pbmFsX2dzKQpsdW1fZW5yaWNoX3JlcwpjYWxjdWxhdGVfc2NvcmUoZGF0YXNldCA9IGFjYzFfY2FuY2VyX2NlbGxzLG15b19nZW5lcyA9IHRvcF9teW8sbHVtX2dlbmVzID0gdG9wX2x1bSxsdW1fdGhyZXNob2xkID0gMixteW9fdGhyZXNob2xkID0gMSkKYGBgCgoKYGBge3J9Cm15b19pbnRlcnNlY3RlZCA9IGludGVyc2VjdCh0b3BfbXlvLG9yaWdpbmFsX215b19nZW5lcykgCmx1bV9pbnRlcnNlY3RlZCA9IGludGVyc2VjdCh0b3BfbHVtLG9yaWdpbmFsX2x1bV9nZW5lcykgCm1lc3NhZ2UoImdlbmVzIGluIG15byBzY29yZToiKQpteW9faW50ZXJzZWN0ZWQKCm1lc3NhZ2UoImdlbmVzIGluIGx1bSBzY29yZToiKQpsdW1faW50ZXJzZWN0ZWQKY2FsY3VsYXRlX3Njb3JlKGRhdGFzZXQgPSBhY2MxX2NhbmNlcl9jZWxscyxteW9fZ2VuZXMgPSBteW9faW50ZXJzZWN0ZWQsbHVtX2dlbmVzID0gbHVtX2ludGVyc2VjdGVkLGx1bV90aHJlc2hvbGQgPSAyLG15b190aHJlc2hvbGQgPSAxKQpgYGAKCgoKIyMjIGVucmljaGVkIGdlbmVzCmBgYHtyfQpyb3duYW1lcyhsdW1fZW5yaWNoX3JlcykgPSBsdW1fZW5yaWNoX3JlcyRwYXRod2F5X25hbWUKbHVtX2VucmljaGVkX2dlbmVzID0gbHVtX2VucmljaF9yZXNbMywiZ2VuZUlEIl0gJT4lIHN0cnNwbGl0KHNwbGl0ID0gIi8iKSAlPiUgLltbMV1dICU+JSBjKC4sbHVtX3Byb3RlaW5fbWFya2VycykgI2FkZCBvcmlnaW5hbCBtYXJrZXJzCmBgYAoKYGBge3J9CnJvd25hbWVzKG15b19lbnJpY2hfcmVzKSA9IG15b19lbnJpY2hfcmVzJHBhdGh3YXlfbmFtZQpteW9fZW5yaWNoZWRfZ2VuZXMgPSBteW9fZW5yaWNoX3Jlc1szLCJnZW5lSUQiXSAlPiUgc3Ryc3BsaXQoc3BsaXQgPSAiLyIpICU+JSAuW1sxXV0gJT4lIGMoLixteW9fcHJvdGVpbl9tYXJrZXJzKSAjYWRkIG9yaWdpbmFsIG1hcmtlcnMKYGBgCgpgYGB7cn0KbWVzc2FnZSgiZ2VuZXMgaW4gbXlvIHNjb3JlOiIpCm15b19lbnJpY2hlZF9nZW5lcwoKbWVzc2FnZSgiZ2VuZXMgaW4gbHVtIHNjb3JlOiIpCmx1bV9lbnJpY2hlZF9nZW5lcwoKY2FsY3VsYXRlX3Njb3JlKGRhdGFzZXQgPSBhY2MxX2NhbmNlcl9jZWxscyxteW9fZ2VuZXMgPSBteW9fZW5yaWNoZWRfZ2VuZXMsbHVtX2dlbmVzID0gbHVtX2VucmljaGVkX2dlbmVzLGx1bV90aHJlc2hvbGQgPSAwLG15b190aHJlc2hvbGQgPSAtMSkKYGBgCgoKIyMjIGVucmljaGVkIGdlbmVzIGFuZCBpbiBvcmlnaW5hbCBzY29yZQpgYGB7cn0KbXlvX2VucmljaGVkX2dlbmVzID0gbXlvX2VucmljaGVkX2dlbmVzW215b19lbnJpY2hlZF9nZW5lcyAlaW4lIG9yaWdpbmFsX215b19nZW5lc10KbHVtX2VucmljaGVkX2dlbmVzID0gbHVtX2VucmljaGVkX2dlbmVzW2x1bV9lbnJpY2hlZF9nZW5lcyAlaW4lIG9yaWdpbmFsX2x1bV9nZW5lc10KCm1lc3NhZ2UoImdlbmVzIGluIG15byBzY29yZToiKQpteW9fZW5yaWNoZWRfZ2VuZXMKCm1lc3NhZ2UoImdlbmVzIGluIGx1bSBzY29yZToiKQpsdW1fZW5yaWNoZWRfZ2VuZXMKCmNhbGN1bGF0ZV9zY29yZShkYXRhc2V0ID0gYWNjMV9jYW5jZXJfY2VsbHMsbXlvX2dlbmVzID0gbXlvX2VucmljaGVkX2dlbmVzLGx1bV9nZW5lcyA9IGx1bV9lbnJpY2hlZF9nZW5lcyxsdW1fdGhyZXNob2xkID0gMixteW9fdGhyZXNob2xkID0gMikKYGBgCgoKIyBIUFYKCgpPbmx5IEhNU0MgY2FuY2VyIGNlbGxzOgoKYGBge3J9CkhQVjMzX1AzID0gZnJlYWQoIi4vRGF0YS9IUFYzM19QMy50eHQiLGNvbC5uYW1lcyA9IGMoInBsYXRlIiwicmVhZHMiKSkgJT4lIGFzLmRhdGEuZnJhbWUoKQpIUFYzM19QMy5kZiA9IEhQVjMzX1AzICU+JSBtdXRhdGUoCiAgcGxhdGUgPSBnc3ViKHggPUhQVjMzX1AzJHBsYXRlLCByZXBsYWNlbWVudCA9ICIiLHBhdHRlcm4gPSAiXy4qJCIpIAogICU+JSBnc3ViKHBhdHRlcm4gPSAiLVAiLHJlcGxhY2VtZW50ID0gIi5QIikgCiAgJT4lIGdzdWIocGF0dGVybiA9ICItIixyZXBsYWNlbWVudCA9ICJfIiwpCiAgKQpIUFYzM19QMy5kZiA9IEhQVjMzX1AzLmRmICU+JSBkcGx5cjo6ZmlsdGVyKEhQVjMzX1AzLmRmJHBsYXRlICVpbiUgY29sbmFtZXMoYWNjMV9jYW5jZXJfY2VsbHMpKQpyb3duYW1lcyhIUFYzM19QMy5kZikgIDwtIEhQVjMzX1AzLmRmJHBsYXRlCkhQVjMzX1AzLmRmJHBsYXRlID0gTlVMTAoKCkhQVjMzX1AyID0gZnJlYWQoIi4vRGF0YS9IUFYzM19QMi50eHQiLGNvbC5uYW1lcyA9IGMoInBsYXRlIiwicmVhZHMiKSkgJT4lIGFzLmRhdGEuZnJhbWUoKQpIUFYzM19QMi5kZiA9IEhQVjMzX1AyICU+JSBtdXRhdGUoCiAgcGxhdGUgPSBnc3ViKHggPUhQVjMzX1AyJHBsYXRlLCByZXBsYWNlbWVudCA9ICIiLHBhdHRlcm4gPSAiXy4qJCIpIAogICU+JSBnc3ViKHBhdHRlcm4gPSAicGxhdGUyLSIscmVwbGFjZW1lbnQgPSAicGxhdGUyXyIsKQogICU+JSBnc3ViKHBhdHRlcm4gPSAiLSIscmVwbGFjZW1lbnQgPSAiXFwuIiwpCiAgKQpIUFYzM19QMi5kZiA9IEhQVjMzX1AyLmRmICU+JSBkcGx5cjo6ZmlsdGVyKEhQVjMzX1AyLmRmJHBsYXRlICVpbiUgY29sbmFtZXMoYWNjMV9jYW5jZXJfY2VsbHMpKQpyb3duYW1lcyhIUFYzM19QMi5kZikgIDwtIEhQVjMzX1AyLmRmJHBsYXRlCkhQVjMzX1AyLmRmJHBsYXRlID0gTlVMTAoKSFBWMzMgPSByYmluZChIUFYzM19QMy5kZixIUFYzM19QMi5kZikKYWNjMV9jYW5jZXJfY2VsbHMgPSBBZGRNZXRhRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyxtZXRhZGF0YSA9IEhQVjMzLGNvbC5uYW1lID0gIkhQVjMzLnJlYWRzIikKRmVhdHVyZVBsb3QoYWNjMV9jYW5jZXJfY2VsbHMsZmVhdHVyZXMgPSAiSFBWMzMucmVhZHMiLG1heC5jdXRvZmYgPSAxMCkKYGBgCgoKYGBge3J9CgpkYXRhID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLHZhcnMgPSAiSFBWMzMucmVhZHMiKQoKZGF0YSA9IGRhdGEgJT4lIG11dGF0ZSgiMCByZWFkcyIgPSBpZl9lbHNlKGNvbmRpdGlvbiA9IEhQVjMzLnJlYWRzID09IDAsdHJ1ZSA9IDEsZmFsc2UgPSAwKSkKZGF0YSA9IGRhdGEgJT4lIG11dGF0ZSgiMSByZWFkcyIgPSBpZl9lbHNlKGNvbmRpdGlvbiA9IEhQVjMzLnJlYWRzID09IDEsdHJ1ZSA9IDEsZmFsc2UgPSAwKSkKZGF0YSA9IGRhdGEgJT4lIG11dGF0ZSgiMiByZWFkcyIgPSBpZl9lbHNlKGNvbmRpdGlvbiA9IEhQVjMzLnJlYWRzID09IDIsdHJ1ZSA9IDEsZmFsc2UgPSAwKSkKZGF0YSA9IGRhdGEgJT4lIG11dGF0ZSgiMy0yMyByZWFkcyIgPSBpZl9lbHNlKGNvbmRpdGlvbiA9IEhQVjMzLnJlYWRzID49MyAmSFBWMzMucmVhZHMgIDwyNCx0cnVlID0gMSxmYWxzZSA9IDApKQpkYXRhID0gZGF0YSAlPiUgbXV0YXRlKCIyNCsgcmVhZHMiID0gaWZfZWxzZShjb25kaXRpb24gPSBIUFYzMy5yZWFkcyA+PTI0LHRydWUgPSAxLGZhbHNlID0gMCkpCmRhdGEgPSBjb2xTdW1zKGRhdGFbLDI6bmNvbChkYXRhKV0pICU+JSBhcy5kYXRhLmZyYW1lKCkKbmFtZXMoZGF0YSlbMV0gPSAiY291bnQiCmRhdGEgPSByb3duYW1lc190b19jb2x1bW4oZGF0YSx2YXIgPSAiYmluIikKZGF0YQpnZ3Bsb3QoZGF0YT1kYXRhLCBhZXMoeD1mYWN0b3IoYmluLGxldmVscyA9IGMoIjAgcmVhZHMiLCIxIHJlYWRzIiwiMiByZWFkcyIsIjMtMjMgcmVhZHMiLCIyNCsgcmVhZHMiKSksIHk9Y291bnQpKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBmaWxsPSJzdGVlbGJsdWUiKSArIHhsYWIoIkhQViBSZWFkcyIpKyB0aGVtZV9taW5pbWFsKCkrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1jb3VudCksIHZqdXN0PS0wLjUsIGNvbG9yPSJibGFjayIsIHNpemU9My41KQpgYGAKYGBge3J9CmhwdjMzX3Bvc2l0aXZlID0gSFBWMzMgJT4lIGRwbHlyOjptdXRhdGUoaHB2MzNfcG9zaXRpdmUgPSBjYXNlX3doZW4ocmVhZHMgPj0gMTAgfiAicG9zaXRpdmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRzIDwgMTAgfiAibmVnYXRpdmUiKQopCgoKCmhwdjMzX3Bvc2l0aXZlJHJlYWRzID0gTlVMTAphY2MxX2NhbmNlcl9jZWxscyA9IEFkZE1ldGFEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLG1ldGFkYXRhID0gaHB2MzNfcG9zaXRpdmUpCmBgYAoKYGBge3J9CkRpbVBsb3Qob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsZ3JvdXAuYnkgID0gYygiaHB2MzNfcG9zaXRpdmUiKSxwdC5zaXplID0gMikKYGBgCmBgYHtyfQphY2MxX2NhbmNlcl9jZWxscyRwbGF0ZSA9IGFjYzFfY2FuY2VyX2NlbGxzJG9yaWcuaWRlbnQKc2F2ZVJEUyhvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscywgZmlsZSA9ICIuL0RhdGEvYWNjMV9jYW5jZXJfY2VsbHNfMTVLbkNvdW50X1Y0LlJEUyIpCmBgYAoKCiMgY05NRgpgYGB7cn0KbGlicmFyeShyZXRpY3VsYXRlKQpgYGAKCmBgYHtyfQojd3JpdGUgZXhwcmVzc2lvbgpuZmVhdHVyZXMgPSAxMDAwMApuZmVhdHVyZXNfbmFtZSA9IChuZmVhdHVyZXMvMTAwMCkgJT4lIGFzLmNoYXJhY3RlcigpCmFjYzFfY2FuY2VyX2NlbGxzID0gRmluZFZhcmlhYmxlRmVhdHVyZXMob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsbmZlYXR1cmVzID0gbmZlYXR1cmVzKQp2YXJnZW5lcyA9IFZhcmlhYmxlRmVhdHVyZXMob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMpCmhtc2NfZXhwcmVzc2lvbiA9IHQoYXMubWF0cml4KEdldEFzc2F5RGF0YShhY2MxX2NhbmNlcl9jZWxscyxzbG90PSdkYXRhJykpKQpobXNjX2V4cHJlc3Npb24gPSAyKipobXNjX2V4cHJlc3Npb24gI2NvbnZlcnQgZnJvbSBsb2cyKHRwbSsxKSB0byB0cG0KaG1zY19leHByZXNzaW9uID0gaG1zY19leHByZXNzaW9uLTEKaG1zY19leHByZXNzaW9uID0gaG1zY19leHByZXNzaW9uWywhY29sU3VtcyhobXNjX2V4cHJlc3Npb249PTAsIG5hLnJtPVRSVUUpPT1ucm93KGhtc2NfZXhwcmVzc2lvbildICNkZWxldGUgcm93cyB0aGF0IGhhdmUgYWxsIDAKaG1zY19leHByZXNzaW9uID0gaG1zY19leHByZXNzaW9uWyx2YXJnZW5lc10Kd3JpdGUudGFibGUoeCA9IGhtc2NfZXhwcmVzc2lvbiAsZmlsZSA9IHBhc3RlMCgnLi9EYXRhL2NOTUYvaG1zY19leHByZXNzaW9uRGF0YV8nLG5mZWF0dXJlc19uYW1lLCdLdmFyZ2VuZXMudHh0Jyksc2VwID0gIlx0IikKYGBgCgoKCmBgYHtweXRob24gZXZhbD1GfQpmcm9tIGNubWYgaW1wb3J0IGNOTUYKaW1wb3J0IG51bXB5IGFzIG5wCm5mZWF0dXJlc19uYW1lID0gci5uZmVhdHVyZXNfbmFtZQpuYW1lID0gJ0hNU0NfY05NRl8nK25mZWF0dXJlc19uYW1lKydLdmFyZ2VuZXMnCm91dGRpciA9ICcuL0RhdGEvY05NRicKS19yYW5nZSA9IG5wLmFyYW5nZSgzLDEwKQpjbm1mX29iaiA9IGNOTUYob3V0cHV0X2Rpcj1vdXRkaXIsIG5hbWU9bmFtZSkKY291bnRzX2ZuPScuL0RhdGEvY05NRi9obXNjX2V4cHJlc3Npb25EYXRhXycrbmZlYXR1cmVzX25hbWUrJ0t2YXJnZW5lcy50eHQnCnRwbV9mbiA9IGNvdW50c19mbiAjIyBUaGlzIGlzIGEgd2VpcmQgY2FzZSB3aGVyZSBiZWNhdXNlIHRoaXMgZGF0YXNldCBpcyBub3QgMycgZW5kIHVtaSBzZXF1ZW5jaW5nLCB3ZSBvcHRlZCB0byB1c2UgdGhlIFRQTSBtYXRyaXggYXMgdGhlIGlucHV0IG1hdHJpeCByYXRoZXIgdGhhbiB0aGUgY291bnQgbWF0cml4Cgpjbm1mX29iai5wcmVwYXJlKGNvdW50c19mbj1jb3VudHNfZm4sIGNvbXBvbmVudHM9S19yYW5nZSwgc2VlZD0xNCx0cG1fZm49dHBtX2ZuKQpgYGAKCmBgYHtweXRob24gZXZhbD1GfQpjbm1mX29iai5mYWN0b3JpemUod29ya2VyX2k9MCwgdG90YWxfd29ya2Vycz0xKQpgYGAKCmBgYHtweXRob24gZXZhbD1GfQpjbm1mX29iai5jb21iaW5lKCkKY25tZl9vYmoua19zZWxlY3Rpb25fcGxvdCgpCmBgYAojIyBTYXZlIG9iamVjdApgYGB7cHl0aG9uIGV2YWw9Rn0KIyBpbXBvcnQgcGlja2xlCiMgZiA9IG9wZW4oJy4vRGF0YS9jTk1GL0hNU0NfY05NRl8nK25mZWF0dXJlc19uYW1lKydLdmFyZ2VuZXMvY25tZl9vYmoucGNrbCcsICd3YicpCiMgcGlja2xlLmR1bXAoY25tZl9vYmosIGYpCiMgZi5jbG9zZSgpCmBgYAoKCiMjIExvYWQgb2JqZWN0CmBgYHtweXRob259CmZyb20gY25tZiBpbXBvcnQgY05NRgppbXBvcnQgcGlja2xlCm5mZWF0dXJlcyA9ICIySyIKZiA9IG9wZW4oJy4vRGF0YS9jTk1GL0hNU0NfY05NRl8nICsgbmZlYXR1cmVzKyAndmFyZ2VuZXMvY25tZl9vYmoucGNrbCcsICdyYicpCmNubWZfb2JqID0gcGlja2xlLmxvYWQoZikKZi5jbG9zZSgpCmBgYAoKCmBgYHtweXRob259CnNlbGVjdGVkX2sgPSA0CmRlbnNpdHlfdGhyZXNob2xkID0gMC4xCmNubWZfb2JqLmNvbnNlbnN1cyhrPXNlbGVjdGVkX2ssIGRlbnNpdHlfdGhyZXNob2xkPWRlbnNpdHlfdGhyZXNob2xkLHNob3dfY2x1c3RlcmluZz1UcnVlKQp1c2FnZV9ub3JtLCBnZXBfc2NvcmVzLCBnZXBfdHBtLCB0b3BnZW5lcyA9IGNubWZfb2JqLmxvYWRfcmVzdWx0cyhLPXNlbGVjdGVkX2ssIGRlbnNpdHlfdGhyZXNob2xkPWRlbnNpdHlfdGhyZXNob2xkKQpgYGAKCmBgYHtyfQpnZXBfc2NvcmVzID0gcHkkZ2VwX3Njb3JlcwpnZXBfdHBtID0gcHkkZ2VwX3RwbQphbGxfbWV0YWdlbmVzPSBweSR1c2FnZV9ub3JtCmBgYAoKIyMgRW5yaWNobWVudCBhbmFseXNpcyBieSB0b3AgMjAwIGdlbmVzIG9mIGVhY2ggcHJvZ3JhbQpgYGB7ciBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD04LCByZXN1bHRzPSdoaWRlJ30KcGx0X2xpc3QgPSBsaXN0KCkKZm9yIChpIGluIDE6bmNvbChnZXBfc2NvcmVzKSkgewogIHRvcF9nZW5lcyA9IGdlcF9zY29yZXMgICU+JSAgYXJyYW5nZShkZXNjKGdlcF9zY29yZXNbaV0pKSAjc29ydCBieSBzY29yZSBhCiAgdG9wID0gaGVhZChyb3duYW1lcyh0b3BfZ2VuZXMpLDIwMCkgI3Rha2UgdG9wIHRvcF9nZW5lc19udW0KICByZXMgPSBnZW5lc192ZWNfZW5yaWNobWVudChnZW5lcyA9IHRvcCxiYWNrZ3JvdW5kID0gcm93bmFtZXMoZ2VwX3Njb3JlcyksaG9tZXIgPSBULHRpdGxlID0gCiAgICAgICAgICAgICAgICAgICAgaSxzaWxlbnQgPSBULHJldHVybl9hbGwgPSBUKQogICAKICBwbHRfbGlzdFtbaV1dID0gcmVzJHBsdAp9CmdyaWRFeHRyYTo6Z3JpZC5hcnJhbmdlKGdyb2JzID0gcGx0X2xpc3QpCmBgYApgYGB7ciBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD04LCByZXN1bHRzPSdoaWRlJ30KCmNhbm9uaWNhbF9wYXRod2F5cyA9IG1zaWdkYnIoc3BlY2llcyA9ICJIb21vIHNhcGllbnMiLCBjYXRlZ29yeSA9ICJDMiIpICU+JSBkcGx5cjo6ZmlsdGVyKGdzX3N1YmNhdCAhPSAiQ0dQIikgJT4lICBkcGx5cjo6ZGlzdGluY3QoZ3NfbmFtZSwgZ2VuZV9zeW1ib2wpIAoKcGx0X2xpc3QgPSBsaXN0KCkKZm9yIChpIGluIDE6bmNvbChnZXBfc2NvcmVzKSkgewogIHRvcF9nZW5lcyA9IGdlcF9zY29yZXMgICU+JSAgYXJyYW5nZShkZXNjKGdlcF9zY29yZXNbaV0pKSAjc29ydCBieSBzY29yZSBhCiAgdG9wID0gaGVhZChyb3duYW1lcyh0b3BfZ2VuZXMpLDIwMCkgI3Rha2UgdG9wIHRvcF9nZW5lc19udW0KICByZXMgPSBnZW5lc192ZWNfZW5yaWNobWVudChnZW5lcyA9IHRvcCxiYWNrZ3JvdW5kID0gcm93bmFtZXMoZ2VwX3Njb3JlcyksaG9tZXIgPSBULHRpdGxlID0gCiAgICAgICAgICAgICAgICAgICAgaSxzaWxlbnQgPSBULHJldHVybl9hbGwgPSBULGN1c3RvbV9wYXRod2F5cyA9IGNhbm9uaWNhbF9wYXRod2F5cykKICAgCiAgcGx0X2xpc3RbW2ldXSA9IHJlcyRwbHQKfQpncmlkRXh0cmE6OmdyaWQuYXJyYW5nZShncm9icyA9IHBsdF9saXN0KQpgYGAKCgpgYGB7cn0KIyBsdW0gZ2VuZXMgaW4gbWV0YWdlbmVzCm1lc3NhZ2UoImx1bSBnZW5lcyBpbiBtZXRhZ2VuZXMiKQpmb3IgKGkgaW4gMTpuY29sKGdlcF9zY29yZXMpKSB7CiAgdG9wX2dlbmVzID0gZ2VwX3Njb3JlcyAgJT4lICBhcnJhbmdlKGRlc2MoZ2VwX3Njb3Jlc1tpXSkpICNzb3J0IGJ5IHNjb3JlIGEKICB0b3AgPSBoZWFkKHJvd25hbWVzKHRvcF9nZW5lcyksMjAwKSAjdGFrZSB0b3AgdG9wX2dlbmVzX251bQogIGNhdChwYXN0ZTAoIm1ldGFnZW5lICIsaSwiOiAiKSkKICBwcmludChvcmlnaW5hbF9sdW1fZ2VuZXNbb3JpZ2luYWxfbHVtX2dlbmVzICVpbiUgdG9wXSkKCn0KY2F0KCJcbiIpCgoKIyBteW8gZ2VuZXMgaW4gbWV0YWdlbmVzCm1lc3NhZ2UoIm15byBnZW5lcyBpbiBtZXRhZ2VuZXMiKQpmb3IgKGkgaW4gMTpuY29sKGdlcF9zY29yZXMpKSB7CiAgdG9wX2dlbmVzID0gZ2VwX3Njb3JlcyAgJT4lICBhcnJhbmdlKGRlc2MoZ2VwX3Njb3Jlc1tpXSkpICNzb3J0IGJ5IHNjb3JlIGEKICB0b3AgPSBoZWFkKHJvd25hbWVzKHRvcF9nZW5lcyksMjAwKSAjdGFrZSB0b3AgdG9wX2dlbmVzX251bQogIGNhdChwYXN0ZTAoIm1ldGFnZW5lICIsaSwiOiAiKSkKICBwcmludChvcmlnaW5hbF9teW9fZ2VuZXNbb3JpZ2luYWxfbXlvX2dlbmVzICVpbiUgdG9wXSkKCn0KY2F0KCJcbiIpCgpub3RjaF9nZW5lcyA9IGMoIkpBRzEiLCJKQUcyIiwiTk9UQ0gzIiwiTk9UQ0gyIiwiTk9UQ0gxIiwiRExMMSIsIk1ZQiIsIkhFUzQiLCJIRVkxIiwiSEVZMiIsIk5SQVJQIikKIyBub3RjaCBnZW5lcyBpbiBtZXRhZ2VuZXMKbWVzc2FnZSgibXlvIGdlbmVzIGluIG1ldGFnZW5lcyIpCmZvciAoaSBpbiAxOm5jb2woZ2VwX3Njb3JlcykpIHsKICB0b3BfZ2VuZXMgPSBnZXBfc2NvcmVzICAlPiUgIGFycmFuZ2UoZGVzYyhnZXBfc2NvcmVzW2ldKSkgI3NvcnQgYnkgc2NvcmUgYQogIHRvcCA9IGhlYWQocm93bmFtZXModG9wX2dlbmVzKSwyMDApICN0YWtlIHRvcCB0b3BfZ2VuZXNfbnVtCiAgY2F0KHBhc3RlMCgibWV0YWdlbmUgIixpLCI6ICIpKQogIHByaW50KG5vdGNoX2dlbmVzW25vdGNoX2dlbmVzICVpbiUgdG9wXSkKCn0KY2F0KCJcbiIpCmBgYAoKCgoKYGBge3J9CnBsdF9saXN0ID0gbGlzdCgpCmZvciAoaSBpbiAxOm5jb2woZ2VwX3Njb3JlcykpIHsKICB0b3BfZ2VuZXMgPSBnZXBfc2NvcmVzICAlPiUgIGFycmFuZ2UoZGVzYyhnZXBfc2NvcmVzW2ldKSkgI3NvcnQgYnkgc2NvcmUgYQogIHRvcCA9IGhlYWQocm93bmFtZXModG9wX2dlbmVzKSwxMCkgI3Rha2UgdG9wIHRvcF9nZW5lc19udW0KICBtZXNzYWdlKHBhc3RlKCJwcm9ncmFtICIsaSwidG9wIGdlbmVzOiIpKQogIHByaW50KHRvcCkKCn0KYGBgCgoKYGBge3IgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTEwfQojIE1ha2UgbWV0YWdlbmUgbmFtZXMKZm9yIChpIGluIDE6bmNvbChhbGxfbWV0YWdlbmVzKSkgewogIGNvbG5hbWVzKGFsbF9tZXRhZ2VuZXMpW2ldID0gIm1ldGFnZW5lLiIgJT4lIHBhc3RlMChpKQp9CgojYWRkIGVhY2ggbWV0YWdlbmUgdG8gbWV0YWRhdGEKZm9yIChpIGluIDE6bmNvbChhbGxfbWV0YWdlbmVzKSkgewogIG1ldGFnZV9tZXRhZGF0YSA9IGFsbF9tZXRhZ2VuZXMgJT4lIHNlbGVjdChpKQogIGFjYzFfY2FuY2VyX2NlbGxzID0gQWRkTWV0YURhdGEob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsbWV0YWRhdGEgPSBtZXRhZ2VfbWV0YWRhdGEpCn0KCkZlYXR1cmVQbG90KG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLGZlYXR1cmVzID0gY29sbmFtZXMoYWxsX21ldGFnZW5lcyksbWF4LmN1dG9mZiA9IDEpCgpgYGAKCgpgYGB7cn0KbWV0YTMgPSBGZXRjaERhdGEob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsdmFycyA9IGMoIm1ldGFnZW5lLjMiKSkKZ2dwbG90KG1ldGEzLCBhZXMoeD1tZXRhZ2VuZS4zKSkgKyAKICBnZW9tX2RlbnNpdHkoKQptZXRhM1ssMV0gPSBhcy5udW1lcmljKG1ldGEzWywxXSkKc3VtKG1ldGEzWywxXT4wLG5hLnJtID0gVCApCnN1bShtZXRhM1ssMV09PTAsbmEucm0gPSBUICkKCmBgYApgYGB7ciBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTB9Cgpub19uZWcgPC0gZnVuY3Rpb24oeCkgewogIHggPSB4ICsgYWJzKG1pbih4KSkKICB4Cn0KCnN1bV8yX29uZSA8LSBmdW5jdGlvbih4KSB7CiAgeCA9eC9zdW0oeCkKICB4Cn0KYWxsX21ldGFnZW5lc19ub3JtPSBzY2FsZShhbGxfbWV0YWdlbmVzKSAlPiUgYXMuZGF0YS5mcmFtZSgpCiMgTWFrZSBtZXRhZ2VuZSBuYW1lcwpmb3IgKGkgaW4gMTpuY29sKGFsbF9tZXRhZ2VuZXNfbm9ybSkpIHsKICBjb2xuYW1lcyhhbGxfbWV0YWdlbmVzX25vcm0pW2ldID0gIm1ldGFnZW5lLiIgJT4lIHBhc3RlMChpKQp9CgojYWRkIGVhY2ggbWV0YWdlbmUgdG8gbWV0YWRhdGEKZm9yIChpIGluIDE6bmNvbChhbGxfbWV0YWdlbmVzX25vcm0pKSB7CiAgbWV0YWdlX21ldGFkYXRhID0gYWxsX21ldGFnZW5lc19ub3JtICU+JSBzZWxlY3QoaSkKICBhY2MxX2NhbmNlcl9jZWxscyA9IEFkZE1ldGFEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLG1ldGFkYXRhID0gbWV0YWdlX21ldGFkYXRhKQp9CgpGZWF0dXJlUGxvdChvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyxmZWF0dXJlcyA9IGNvbG5hbWVzKGFsbF9tZXRhZ2VuZXNfbm9ybSksbWF4LmN1dG9mZiA9IDAuNSkKCmBgYAoKIyMgYXNzaWdubWVudCBVTUFQCmBgYHtyfQpsYXJnZXJfYnkgPSAyCm1lc3NhZ2UocGFzdGUoImxhcmdlcl9ieSA9ICIsIGxhcmdlcl9ieSkpCmFjYzFfY2FuY2VyX2NlbGxzID0gcHJvZ3JhbV9hc3NpZ25tZW50KGRhdGFzZXQgPSBhY2MxX2NhbmNlcl9jZWxscyxsYXJnZXJfYnkgPSBsYXJnZXJfYnkscHJvZ3JhbV9uYW1lcyA9IGNvbG5hbWVzKGFsbF9tZXRhZ2VuZXMpKQpzZWxlY3RlZF9rID00CmNvbG9ycyA9ICByYWluYm93KHNlbGVjdGVkX2spCmNvbG9ycyA9IGMoY29sb3JzLCJncmV5IikKRGltUGxvdChhY2MxX2NhbmNlcl9jZWxscyxncm91cC5ieSA9ICJwcm9ncmFtLmFzc2lnbm1lbnQiLHB0LnNpemUgPSAyLGNvbHMgPWNvbG9ycykKYGBgIAoKc2hvdyBjZWxsIGN5Y2xlIHByb2dyYW06CmBgYHtyIHdhcm5pbmc9RkFMU0V9CmhhbGxtYXJrX25hbWUgPSAiR09fTUlUT1RJQ19DRUxMX0NZQ0xFIgpnZW5lc2V0cyAgPUdTRUFCYXNlOjpnZXRHbXQoIi4vRGF0YS9oLmFsbC52Ny4wLnN5bWJvbHMucGx1c2NjLmdtdCIpCnZhcl9mZWF0dXJlcz1hY2MxX2NhbmNlcl9jZWxsc0Bhc3NheXMkUk5BQHZhci5mZWF0dXJlcwpnZW5lSWRzPSBnZW5lc2V0c1tbaGFsbG1hcmtfbmFtZV1dQGdlbmVJZHMKc2NvcmUgPC0gYXBwbHkoYWNjMV9jYW5jZXJfY2VsbHNAYXNzYXlzJFJOQUBkYXRhW2ludGVyc2VjdChnZW5lSWRzLHZhcl9mZWF0dXJlcyksXSwyLG1lYW4pCmFjYzFfY2FuY2VyX2NlbGxzPUFkZE1ldGFEYXRhKGFjYzFfY2FuY2VyX2NlbGxzLHNjb3JlLGhhbGxtYXJrX25hbWUpCmBgYAoKYGBge3J9CkZlYXR1cmVQbG90KG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLGZlYXR1cmVzID0gaGFsbG1hcmtfbmFtZSkKCmBgYApgYGB7cn0KY2NfdnNfcHJvZ3JhbTIgPSBGZXRjaERhdGEob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsdmFycyA9IGMoIm1ldGFnZW5lLjIiLGhhbGxtYXJrX25hbWUpKQpjb3IoY2NfdnNfcHJvZ3JhbTJbMV0sY2NfdnNfcHJvZ3JhbTJbMl0pCmBgYAoKIyMgQ29tcGFyaXNpb25zCgoKYGBge3J9CmNudl92c19ocHYgPSBGZXRjaERhdGEob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsdmFycyA9IGMoImNudi5jbHVzdGVyIiwiaHB2MzNfcG9zaXRpdmUiKSkKdGVzdCA8LSBmaXNoZXIudGVzdCh0YWJsZShjbnZfdnNfaHB2KSkKZ2diYXJzdGF0cygKICBjbnZfdnNfaHB2LCBjbnYuY2x1c3RlciwgaHB2MzNfcG9zaXRpdmUsCiAgcmVzdWx0cy5zdWJ0aXRsZSA9IEZBTFNFLAogIHN1YnRpdGxlID0gcGFzdGUwKAogICAgIkZpc2hlcidzIGV4YWN0IHRlc3QiLCAiLCBwLXZhbHVlID0gIiwKICAgIGlmZWxzZSh0ZXN0JHAudmFsdWUgPCAwLjAwMSwgIjwgMC4wMDEiLCByb3VuZCh0ZXN0JHAudmFsdWUsIDMpKQogICkKKQoKYGBgCgpgYGB7cn0KY252X3ZzX2NubWYgPSBGZXRjaERhdGEob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsdmFycyA9IGMoInByb2dyYW0uYXNzaWdubWVudCIsImNudi5jbHVzdGVyIikpCmNudl92c19jbm1mID0gY252X3ZzX2NubWYgJT4lIGRwbHlyOjpmaWx0ZXIocHJvZ3JhbS5hc3NpZ25tZW50ID09ICIxIiB8cHJvZ3JhbS5hc3NpZ25tZW50ID09ICIyIiApCnRlc3QgPC0gZmlzaGVyLnRlc3QodGFibGUoY252X3ZzX2NubWYpKQpnZ2JhcnN0YXRzKAogIGNudl92c19jbm1mLCBwcm9ncmFtLmFzc2lnbm1lbnQsIGNudi5jbHVzdGVyLAogIHJlc3VsdHMuc3VidGl0bGUgPSBGQUxTRSwKICBzdWJ0aXRsZSA9IHBhc3RlMCgKICAgICJGaXNoZXIncyBleGFjdCB0ZXN0IiwgIiwgcC12YWx1ZSA9ICIsCiAgICBpZmVsc2UodGVzdCRwLnZhbHVlIDwgMC4wMDEsICI8IDAuMDAxIiwgcm91bmQodGVzdCRwLnZhbHVlLCAzKSkKICApCikKCmBgYAoKYGBge3J9CmNubWZfdnNfaHB2ID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLHZhcnMgPSBjKCJwcm9ncmFtLmFzc2lnbm1lbnQiLCJocHYzM19wb3NpdGl2ZSIpKQpjbm1mX3ZzX2hwdiA9IGNubWZfdnNfaHB2ICU+JSBkcGx5cjo6ZmlsdGVyKHByb2dyYW0uYXNzaWdubWVudCA9PSAiMSIgfHByb2dyYW0uYXNzaWdubWVudCA9PSAiMiIgKQp0ZXN0IDwtIGZpc2hlci50ZXN0KHRhYmxlKGNubWZfdnNfaHB2KSkKZ2diYXJzdGF0cygKICBjbm1mX3ZzX2hwdiwgcHJvZ3JhbS5hc3NpZ25tZW50LCBocHYzM19wb3NpdGl2ZSwKICByZXN1bHRzLnN1YnRpdGxlID0gRkFMU0UsCiAgc3VidGl0bGUgPSBwYXN0ZTAoCiAgICAiRmlzaGVyJ3MgZXhhY3QgdGVzdCIsICIsIHAtdmFsdWUgPSAiLAogICAgaWZlbHNlKHRlc3QkcC52YWx1ZSA8IDAuMDAxLCAiPCAwLjAwMSIsIHJvdW5kKHRlc3QkcC52YWx1ZSwgMykpCiAgKQopCgpgYGAKCmBgYHtyfQpteWJfdnNfY252ID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLHZhcnMgPSBjKCJjbnYuY2x1c3RlciIsIk1ZQiIpKQpteWJfdnNfY252ICRjbnYuY2x1c3RlciA9IGFzLmNoYXJhY3RlcihteWJfdnNfY252ICRjbnYuY2x1c3RlciApCgpnZ2JveHBsb3QobXliX3ZzX2NudiwgeCA9ICJjbnYuY2x1c3RlciIsIHkgPSAiTVlCIiwKICAgICAgICAgIHBhbGV0dGUgPSAiamNvIiwKICAgICAgICAgIGFkZCA9ICJqaXR0ZXIiKSsgc3RhdF9jb21wYXJlX21lYW5zKG1ldGhvZCA9ICJ3aWxjb3gudGVzdCIsY29tcGFyaXNvbnMgPSBsaXN0KGMoIjEiLCIyIikpKQpgYGAKCgpgYGB7cn0KbXliX3ZzX2hwdiA9IEZldGNoRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyx2YXJzID0gYygiaHB2MzNfcG9zaXRpdmUiLCJNWUIiKSkKbXliX3ZzX2hwdiAkaHB2MzNfcG9zaXRpdmUgPSBhcy5jaGFyYWN0ZXIobXliX3ZzX2hwdiAkaHB2MzNfcG9zaXRpdmUgKQoKZ2dib3hwbG90KG15Yl92c19ocHYsIHggPSAiaHB2MzNfcG9zaXRpdmUiLCB5ID0gIk1ZQiIsCiAgICAgICAgICBwYWxldHRlID0gImpjbyIsCiAgICAgICAgICBhZGQgPSAiaml0dGVyIikrIHN0YXRfY29tcGFyZV9tZWFucyhtZXRob2QgPSAid2lsY294LnRlc3QiLGNvbXBhcmlzb25zID0gbGlzdChjKCJwb3NpdGl2ZSIsIm5lZ2F0aXZlIikpKSsgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gZnVuY3Rpb24oeCkgZGF0YS5mcmFtZSh5PTE1LCBsYWJlbCA9IHBhc3RlKCJNZWFuPSIscm91bmQobWVhbih4KSxkaWdpdHMgPSAyKSkpLCBnZW9tPSJ0ZXh0IikgK3lsYWIoImxvZzIoTVlCKSIpCmBgYAoKCmBgYHtyfQpwbGF0ZV8xX25ldyA9IHN1YnNldChhY2MxX2NhbmNlcl9jZWxscyxzdWJzZXQgPSBvcmlnLmlkZW50ID09ICJBQ0MucGxhdGUyIikKbXliX3ZzX2hwdiA9IEZldGNoRGF0YShvYmplY3QgPSBwbGF0ZV8xX25ldyx2YXJzID0gYygiaHB2MzNfcG9zaXRpdmUiLCJNWUIiKSkKbXliX3ZzX2hwdiAkaHB2MzNfcG9zaXRpdmUgPSBhcy5jaGFyYWN0ZXIobXliX3ZzX2hwdiAkaHB2MzNfcG9zaXRpdmUgKQoKIyBteWJfdnNfaHB2JE1ZQiA9IDIqKm15Yl92c19ocHYkTVlCCgpwID0gZ2dib3hwbG90KG15Yl92c19ocHYsIHggPSAiaHB2MzNfcG9zaXRpdmUiLCB5ID0gIk1ZQiIsCiAgICAgICAgICBwYWxldHRlID0gImpjbyIsCiAgICAgICAgICBhZGQgPSAiaml0dGVyIikrIHN0YXRfY29tcGFyZV9tZWFucyhtZXRob2QgPSAid2lsY294LnRlc3QiLGNvbXBhcmlzb25zID0gbGlzdChjKCJwb3NpdGl2ZSIsIm5lZ2F0aXZlIikpKSsgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gZnVuY3Rpb24oeCkgZGF0YS5mcmFtZSh5PTE1LCBsYWJlbCA9IHBhc3RlKCJNZWFuPSIscm91bmQobWVhbih4KSxkaWdpdHMgPSAyKSkpLCBnZW9tPSJ0ZXh0IikgK3lsYWIoImxvZzIoTVlCKSIpK2dndGl0bGUoIkFDQy5wbGF0ZTIiKQoKCnBsYXRlXzJfbmV3ID0gc3Vic2V0KGFjYzFfY2FuY2VyX2NlbGxzLHN1YnNldCA9IG9yaWcuaWRlbnQgPT0gIkFDQzEuUDMiKQpteWJfdnNfaHB2ID0gRmV0Y2hEYXRhKG9iamVjdCA9IHBsYXRlXzJfbmV3LHZhcnMgPSBjKCJocHYzM19wb3NpdGl2ZSIsIk1ZQiIpKQpteWJfdnNfaHB2ICRocHYzM19wb3NpdGl2ZSA9IGFzLmNoYXJhY3RlcihteWJfdnNfaHB2ICRocHYzM19wb3NpdGl2ZSApCiMgbXliX3ZzX2hwdiRNWUIgPSAyKipteWJfdnNfaHB2JE1ZQgoKcCsKZ2dib3hwbG90KG15Yl92c19ocHYsIHggPSAiaHB2MzNfcG9zaXRpdmUiLCB5ID0gIk1ZQiIsCiAgICAgICAgICBwYWxldHRlID0gImpjbyIsCiAgICAgICAgICBhZGQgPSAiaml0dGVyIikrIHN0YXRfY29tcGFyZV9tZWFucyhtZXRob2QgPSAid2lsY294LnRlc3QiLGNvbXBhcmlzb25zID0gbGlzdChjKCJwb3NpdGl2ZSIsIm5lZ2F0aXZlIikpKSsgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gZnVuY3Rpb24oeCkgZGF0YS5mcmFtZSh5PTE1LCBsYWJlbCA9IHBhc3RlKCJNZWFuPSIscm91bmQobWVhbih4KSxkaWdpdHMgPSAyKSkpLCBnZW9tPSJ0ZXh0IikgK3lsYWIoImxvZzIoTVlCKSIpK2dndGl0bGUoIkFDQzEuUDMiKQpgYGAKCmBgYHtyfQpocHZSZWFkc192c19teWIgPSBGZXRjaERhdGEob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsdmFycyA9IGMoIkhQVjMzLnJlYWRzIiwiTVlCIikpCmNvcnIgPSBjb3IoaHB2UmVhZHNfdnNfbXliJEhQVjMzLnJlYWRzLGhwdlJlYWRzX3ZzX215YiRNWUIpCnByaW50KCJjb3JyZWxhdGlvbiBvZiBNWUIgYWJkIGhwdjMzX3JlYWRzOiIgJT4lIHBhc3RlKGNvcnIgJT4lIHJvdW5kKGRpZ2l0cyA9IDIpKSkKYGBgCgojIFBsYXRlIGJpYXMKYGBge3J9CmFjYzFfY2FuY2VyX2NlbGxzX2RhdGEgPSBhY2MxX2NhbmNlcl9jZWxsc0Bhc3NheXNbWyJSTkEiXV1AZGF0YSAlPiUgYXMuZGF0YS5mcmFtZSgpCmFjYzFfY2FuY2VyX2NlbGxzX2RhdGEgPSBjb3IoYWNjMV9jYW5jZXJfY2VsbHNfZGF0YSkKYW5ub3RhdGlvbiA9IEZldGNoRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyx2YXJzID0gYygib3JpZy5pZGVudCIpKQoKY29sb3JzIDwtIGMoc2VxKC0xLDEsYnk9MC4wMSkpCiAgbXlfcGFsZXR0ZSA8LSBjKCJibHVlIixjb2xvclJhbXBQYWxldHRlKGNvbG9ycyA9IGMoImJsdWUiLCAid2hpdGUiLCAicmVkIikpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuID0gbGVuZ3RoKGNvbG9ycyktMyksICJyZWQiKQogIApwaHQxID0gcGhlYXRtYXAoYWNjMV9jb3IsYW5ub3RhdGlvbl9jb2wgID0gYW5ub3RhdGlvbixmb250c2l6ZSA9IDYsYnJlYWtzID0gY29sb3JzLCBjb2xvciA9IG15X3BhbGV0dGUsc2hvd19jb2xuYW1lcyA9IEYsc2hvd19yb3duYW1lcyA9IEYpCmBgYAoKYGBge3J9CmFjYzFfY2FuY2VyX2NlbGxzX2RhdGEgPSBhY2MxX2NhbmNlcl9jZWxsc0Bhc3NheXNbWyJSTkEiXV1AZGF0YSAlPiUgYXMuZGF0YS5mcmFtZSgpCmFjYzFfY2FuY2VyX2NlbGxzX2RhdGEgPSBjb3IoYWNjMV9jYW5jZXJfY2VsbHNfZGF0YSkKYW5ub3RhdGlvbiA9IEZldGNoRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyx2YXJzID0gYygiY252LmNsdXN0ZXIiKSkKCmNvbG9ycyA8LSBjKHNlcSgtMSwxLGJ5PTAuMDEpKQogIG15X3BhbGV0dGUgPC0gYygiYmx1ZSIsY29sb3JSYW1wUGFsZXR0ZShjb2xvcnMgPSBjKCJibHVlIiwgIndoaXRlIiwgInJlZCIpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAobiA9IGxlbmd0aChjb2xvcnMpLTMpLCAicmVkIikKICAKcGh0MSA9IHBoZWF0bWFwKGFjYzFfY29yLGFubm90YXRpb25fY29sICA9IGFubm90YXRpb24sZm9udHNpemUgPSA2LGJyZWFrcyA9IGNvbG9ycywgY29sb3IgPSBteV9wYWxldHRlLHNob3dfY29sbmFtZXMgPSBGLHNob3dfcm93bmFtZXMgPSBGKQpgYGAKCgpgYGB7cn0KY252X3ZzX3BsYXRlID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLHZhcnMgPSBjKCJjbnYuY2x1c3RlciIsIm9yaWcuaWRlbnQiKSkKdGVzdCA8LSBmaXNoZXIudGVzdCh0YWJsZShjbnZfdnNfcGxhdGUpKQpnZ2JhcnN0YXRzKAogIGNudl92c19wbGF0ZSwgY252LmNsdXN0ZXIsIG9yaWcuaWRlbnQsCiAgcmVzdWx0cy5zdWJ0aXRsZSA9IEZBTFNFLAogIHN1YnRpdGxlID0gcGFzdGUwKAogICAgIkZpc2hlcidzIGV4YWN0IHRlc3QiLCAiLCBwLXZhbHVlID0gIiwKICAgIGlmZWxzZSh0ZXN0JHAudmFsdWUgPCAwLjAwMSwgIjwgMC4wMDEiLCByb3VuZCh0ZXN0JHAudmFsdWUsIDMpKQogICkKKQoKYGBgCgpgYGB7cn0KIyBjcmVhdCBjb2xvdXJzIGZvciBlYWNoIGdyb3VwCmNudl92c19wbGF0ZSA9IEZldGNoRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyx2YXJzID0gYygiY252LmNsdXN0ZXIiLCJvcmlnLmlkZW50IiwiZ2VuZXNfZGV0ZWN0ZWQiKSkKY252X3ZzX3BsYXRlJGdlbmVzX2RldGVjdGVkW2Nudl92c19wbGF0ZSRnZW5lc19kZXRlY3RlZD44MDAwXSA9IDgwMDAKcm93bmFtZXMoY252X3ZzX3BsYXRlKSA9IHJvd25hbWVzKGNudl92c19wbGF0ZSkgJT4lIGdzdWIocGF0dGVybiA9ICJfIixyZXBsYWNlbWVudCA9ICJcXC4iKQpjbnZfdnNfcGxhdGUkY252LmNsdXN0ZXIgPSBhcy5jaGFyYWN0ZXIoY252X3ZzX3BsYXRlJGNudi5jbHVzdGVyKQpjbnZfdnNfcGxhdGUgPSBjbnZfdnNfcGxhdGUgJT4lIGRwbHlyOjpyZW5hbWUocGxhdGUgPSAib3JpZy5pZGVudCIpCmNudl92c19wbGF0ZSA9IGNudl92c19wbGF0ZSAlPiUgYXJyYW5nZShwbGF0ZSxnZW5lc19kZXRlY3RlZCkKaW5mZXJjbnYub2JzZXJ2YXRpb25zMl9vcmRlcmVkIDwtIGluZmVyY252Lm9ic2VydmF0aW9uczJbbWF0Y2gocm93bmFtZXMoY252X3ZzX3BsYXRlKSwgcm93bmFtZXMoaW5mZXJjbnYub2JzZXJ2YXRpb25zMikgKSxdCgphbm5vQ29sIDwtIGxpc3QocGxhdGUgPSBjKEFDQzEuUDMgPSAicmVkIixBQ0MucGxhdGUyID0gImdyZWVuIiksY252LmNsdXN0ZXIgPWMoIjEiPSJncmVlbiIsIjIiID0gInJlZCIpKQoKcGhlYXRtYXAoaW5mZXJjbnYub2JzZXJ2YXRpb25zMl9vcmRlcmVkLGNsdXN0ZXJfY29scyA9IEYsY2x1c3Rlcl9yb3dzID0gRiwgc2hvd19yb3duYW1lcyA9IEYsc2hvd19jb2xuYW1lcyA9IEYsIGJyZWFrcyA9IGJyZWFrcyxjb2xvciA9IGNvbG9yUmFtcFBhbGV0dGUocmV2KGMoImRhcmtyZWQiLCAid2hpdGUiLCAiZGFya2JsdWUiKSkpKDE1KSxhbm5vdGF0aW9uX3JvdyA9IGNudl92c19wbGF0ZSxhbm5vdGF0aW9uX2NvbG9ycyA9IGFubm9Db2wpCgpgYGAKCmBgYHtyfQojIGNyZWF0IGNvbG91cnMgZm9yIGVhY2ggZ3JvdXAKY252X3ZzX3BsYXRlID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLHZhcnMgPSBjKCJjbnYuY2x1c3RlciIsIm9yaWcuaWRlbnQiKSkKCnJvd25hbWVzKGNudl92c19wbGF0ZSkgPSByb3duYW1lcyhjbnZfdnNfcGxhdGUpICU+JSBnc3ViKHBhdHRlcm4gPSAiXyIscmVwbGFjZW1lbnQgPSAiXFwuIikKY252X3ZzX3BsYXRlJGNudi5jbHVzdGVyID0gYXMuY2hhcmFjdGVyKGNudl92c19wbGF0ZSRjbnYuY2x1c3RlcikKY252X3ZzX3BsYXRlID0gY252X3ZzX3BsYXRlICU+JSBkcGx5cjo6cmVuYW1lKHBsYXRlID0gIm9yaWcuaWRlbnQiKQphbm5vQ29sIDwtIGxpc3QocGxhdGUgPSBjKEFDQzEuUDMgPSAicmVkIixBQ0MucGxhdGUyID0gImdyZWVuIiksY252LmNsdXN0ZXIgPWMoIjEiPSJncmVlbiIsIjIiID0gInJlZCIpKQoKcGhlYXRtYXAoaW5mZXJjbnYub2JzZXJ2YXRpb25zMixjbHVzdGVyX2NvbHMgPSBGLGNsdXN0ZXJfcm93cyA9IEYsIHNob3dfcm93bmFtZXMgPSBGLHNob3dfY29sbmFtZXMgPSBGLCBicmVha3MgPSBicmVha3MsY29sb3IgPSBjb2xvclJhbXBQYWxldHRlKHJldihjKCJkYXJrcmVkIiwgIndoaXRlIiwgImRhcmtibHVlIikpKSgxNSksYW5ub3RhdGlvbl9yb3cgPSBjbnZfdnNfcGxhdGUsYW5ub3RhdGlvbl9jb2xvcnMgPSBhbm5vQ29sKQoKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMH0KZGF0YSA9IEZldGNoRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyx2YXJzID0gYygibWV0YWdlbmUuMSIsIm1ldGFnZW5lLjIiKSkKIyBkYXRhJGdlbmVzX2RldGVjdGVkID0gbWluX21heF9ub3JtYWxpemUoZGF0YSRnZW5lc19kZXRlY3RlZCkKYW5ub3RhdGlvbiA9IEZldGNoRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyx2YXJzID0gYygiZ2VuZXNfZGV0ZWN0ZWQiLCJwcm9ncmFtLmFzc2lnbm1lbnQiLCJvcmlnLmlkZW50IikpCmFubm90YXRpb24gPSBhbm5vdGF0aW9uICU+JSBkcGx5cjo6cmVuYW1lKHBsYXRlID0gIm9yaWcuaWRlbnQiKQphbm5vdGF0aW9uJGdlbmVzX2RldGVjdGVkW2Fubm90YXRpb24kZ2VuZXNfZGV0ZWN0ZWQ+ODAwMF0gPSA4MDAwCmFubm90YXRpb24gPSBhbm5vdGF0aW9uICU+JSBhcnJhbmdlKHBsYXRlLGdlbmVzX2RldGVjdGVkKQpkYXRhIDwtIGRhdGFbbWF0Y2gocm93bmFtZXMoYW5ub3RhdGlvbiksIHJvd25hbWVzKGRhdGEpICksXQphbm5vQ29sIDwtIGxpc3QocHJvZ3JhbS5hc3NpZ25tZW50ID0gYyhtZXRhZ2VuZS4xID0gInJlZCIsbWV0YWdlbmUuMiA9ICJncmV5OTYiLG1ldGFnZW5lLjMgPSAieWVsbG93IixtZXRhZ2VuZS40ID0gImJsdWUiLCJOQSIgPSAiZ3JleSIpLHBsYXRlID0gYyhBQ0MxLlAzID0gInJlZCIsQUNDLnBsYXRlMiA9ICJncmVlbiIpKQoKY29sb3JzIDwtIGMoc2VxKC0xLDEsYnk9MC4wMSkpCiAgbXlfcGFsZXR0ZSA8LSBjKCJibHVlIixjb2xvclJhbXBQYWxldHRlKGNvbG9ycyA9IGMoImJsdWUiLCAid2hpdGUiLCAicmVkIikpCiAgICAgICAgICAgICAgICAgIChuID0gbGVuZ3RoKGNvbG9ycyktMyksICJyZWQiKQogIApwaGVhdG1hcChkYXRhLGNsdXN0ZXJfY29scyA9IEYsY2x1c3Rlcl9yb3dzID0gRixzaG93X3Jvd25hbWVzID0gRixjb2xvciA9IG15X3BhbGV0dGUsIGJyZWFrcyA9IGNvbG9ycyxhbm5vdGF0aW9uX3JvdyA9IGFubm90YXRpb24sYW5ub3RhdGlvbl9jb2xvcnMgPSBhbm5vQ29sKQpgYGAKCgoKYGBge3J9CnBsYXRlXzMgPSBjbm1mX3ZzX3BsYXRlICU+JSBkcGx5cjo6ZmlsdGVyKChwcm9ncmFtLmFzc2lnbm1lbnQgPT0gMSAmIG9yaWcuaWRlbnQgPT0gIkFDQzEuUDMiKSApICU+JSByb3duYW1lcygpIApwbGF0ZV8yID0gY25tZl92c19wbGF0ZSAlPiUgZHBseXI6OmZpbHRlcigocHJvZ3JhbS5hc3NpZ25tZW50ID09IDIgJiBvcmlnLmlkZW50ID09ICJBQ0MucGxhdGUyIikpICU+JSByb3duYW1lcygpCmNlbGxzID0gbGlzdChBQ0MxLlAzID0gcGxhdGVfMyxBQ0MucGxhdGUyICA9IHBsYXRlXzIpCmBgYAojIyBSZXN1bHRzIHsudGFic2V0fQoKCiMjIyBleGNlcHRpb25zCgpgYGB7ciByZXN1bHRzPSdhc2lzJ30KZXhjZXB0aW9uc19wbHQgPSBEaW1QbG90KG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLCBjZWxscy5oaWdobGlnaHQgPSBjZWxscywgY29scy5oaWdobGlnaHQgPSBjKCJncmVlbiIsInJlZCIpLCBjb2xzID0gImdyYXkiLCBvcmRlciA9IFRSVUUscHQuc2l6ZSA9IDIsc2l6ZXMuaGlnaGxpZ2h0ID0gMixjb21iaW5lID0gRikgCmNvbG9ycyA9IGMoImdyZWVuIiwicmVkIiwiY3lhbiIsInB1cnBsZSIsImdyZXkiKQpwcm9ncmFtLmFzc2lnbm1lbnRfcGx0ID0gRGltUGxvdChhY2MxX2NhbmNlcl9jZWxscyxncm91cC5ieSA9ICJwcm9ncmFtLmFzc2lnbm1lbnQiLHB0LnNpemUgPSAyLGNvbHMgPSBjb2xvcnMsY29tYmluZSA9IEYpCm1ldGFnZW5lLjFfcGx0IDwtIEZlYXR1cmVQbG90KG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLGZlYXR1cmVzID0gYygibWV0YWdlbmUuMSIpLGNvbWJpbmUgPSBGKQptZXRhZ2VuZS4yX3BsdCA9IEZlYXR1cmVQbG90KG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLGZlYXR1cmVzID0gYygibWV0YWdlbmUuMiIpLGNvbWJpbmUgPSBGKQoKbHN0ID0gbGlzdChleGNlcHRpb25zID0gZXhjZXB0aW9uc19wbHQsIHByb2dyYW0uYXNzaWdubWVudCA9IHByb2dyYW0uYXNzaWdubWVudF9wbHQsbWV0YWdlbmUuMSA9IG1ldGFnZW5lLjFfcGx0LG1ldGFnZW5lLjIgPSBtZXRhZ2VuZS4yX3BsdCkKCmZvciAoaSBpbiAxOmxlbmd0aChsc3QpKSB7CiAgY2F0KCIjIyMgIixuYW1lcyhsc3QpW2ldLCIgXG4iKQogIHByaW50KAogICAgbHN0W1tpXV0KICAgICkKICBwbG90Lm5ldygpCiAgZGV2Lm9mZigpCiAgY2F0KCcgXG5cbicpCn0KYGBgCgoKCgoKCg==